2023年数据分析师还有前途吗?

发布时间:
2023-08-26 13:33
阅读量:
42

15年,你会用个Excel,透视表玩的6,再会用SQL查询数据,就能找到很好的工作。

17年,你还得会用各种BI可视化工具,用Tableau做一些漂亮的图表,才能找到很好的工作。

20年,你还得会python,写一些自动化的脚本来解决日常重复的工作,才能找到很好的工作。

23年,你除了要会上述提到的技能,还要懂爬虫,还要懂算法,还要懂..........;才能站稳数据分析师的岗位。


接下来我们就用实战走一遍上述技能的全栈流程(文章中提到的数据不商用,不对外售卖,仅个人使用,望理解!)。

全栈路线: 数据采集——>数据清洗——>入库——>统计分析——>挖掘——>可视化;

一、数据采集

博主本人是从事汽车行业的分析师,所以会拿汽车行业的相关数据举例;

我们现在手里没有数据,怎么办?一个字——【爬】,我本次的案例是爬取某网站开源的数据,并且没有对该网站做任何的破坏、攻击等不利行为,下述文章中隐藏该网站url,如读者想深度讨论,可与我私聊;

import requests import pandas as pd import random import time from datetime import datetime from lxml import etree # 参数区,每次需要更改时间和页面数量 date = '2022-01' page = 666 headers = { 'user-agent':'在开发者工具中寻找自己的agent', 'Cookie':'在开发者工具中寻找自己的cookie' } # 创建一个空的DataFrame data = pd.DataFrame(columns=['排名', '车型', '城市', '上牌量', '级别', '指导价(万元)']) time_start = datetime.now() for i in range(1,page+1,1): print(f"开始爬取第{i}页") #地址 url = f'https://url{date}url{i}.html' #请求地址 resp = requests.get(url,headers = headers) resp.close() # 解析HTML tree = etree.HTML(resp.text) # 使用XPath提取数据 rows = tree.xpath('//html/body/div[5]/div[3]/div[2]/div[2]/table/tbody/tr') # 遍历每一行数据并添加到DataFrame中 for row in rows: rank = row.xpath('./td[1]/strong/text()')[0] model = row.xpath('./td[2]/a/text()')[0] city = row.xpath('./td[3]/a/text()')[0] sales = row.xpath('./td[4]/a/em/text()')[0] category = row.xpath('./td[5]/a/text()')[0] price = row.xpath('./td[6]/a/span/text()')[0] #依次注入最新数据 data = pd.concat([data, pd.DataFrame({'排名': [rank], '车型': [model], '城市': [city], '上牌量': [sales], '级别': [category], '指导价(万元)': [price]})], ignore_index=True) # 为避免反扒 和 保护该网站 ,将每次的爬取时间设置的长一点,在6-11秒随机停顿一会 time.sleep(random.randint(6, 11)) print(f"第{i}页怕取完成") # 查看爬取进度 time_end = datetime.now() print("已耗时" + str(time_end - time_start)) print(f"还剩下{page - i}页,预计花费{round(((page-i)*8.5/60),2)}min") if(i%50 == 0): data.to_excel(f"{date}全国车型上险数据.xlsx") print("爬取完成")

以上代码运行完毕,会得到一份如下图所示的数据(图1-1),该数据包含了,2022年全年——2023年截止至今的车型by城市的销量数据。

图1-1

二、清洗

清洗是数据工作中很头疼的内容,

它不仅考验你的技术功底(用各种千奇百怪、五花八门的技巧来解决数据问题

还考验你对业务的理解程度(要找到车型品牌的映射关系表,也就是还需要再爬取一遍其他网站的数据,你最终要校验清洗结果是否准确,所以你脑子里要了解每款车型对应的品牌是什么,这就需要沉淀了)

以上过程较为复杂,且方向很定制化,该过程不做描述,直接展示清洗后的结果,如下图1-2。

图1-2

三、入库

我这里使用的是mysql数据库,具体的安装流程见如下链接:

mac装mysql?

接下来我们用python连接mysql服务器,将数据库存入mysql

import pandas as pd import mysql.connector # 建立数据库连接 conn = mysql.connector.connect( host='localhost', user='root', password='password', database='car_data' ) cursor = conn.cursor() # 读取Excel文件 excel_data = pd.read_excel(f'data_source.xlsx') # 循环遍历Excel数据,并插入数据库 for index, row in excel_data.iterrows(): # 替换为Excel中相应字段的名称 ranking = row['ranking'] brand = row['brand'] model = row['model'] city = row['city'] sales = row['sales'] level = row['level'] month = row['month'] min_price = row['min_price'] max_price = row['max_price'] # 构建插入语句 sql = "INSERT INTO cars_insurance_sales (ranking, brand, model, city, sales, level, month, min_price, max_price) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)" # 执行插入语句 values = (ranking, brand, model, city, sales, level, month, min_price, max_price) cursor.execute(sql, values) # 提交更改并关闭连接 conn.commit() cursor.close() conn.close() print("数据全部插入完成")

四、统计分析

数据已经准备好了,接下来我们做点好玩的事情

我们先来看一下北京哪些品牌卖的好,如果直观的把每个品牌做销量降序没有意思,我们引入一个观点,把品牌定级,占据北京前30%销量的品牌列为头部品牌,中间40%销量的品牌列为腰部品牌,最后30%销量的品牌列为尾部品牌,此处需要用到mysql的窗口函数sum() over(partition by [] order by []),具体方案如下:

import pandas as pd import mysql.connector import matplotlib.pyplot as plt # 建立数据库连接 conn = mysql.connector.connect( host='localhost', user='root', password='password', database='car_data' ) # 创建游标对象 cursor = conn.cursor() # 执行SQL查询 query = """ SELECT *, CASE WHEN accumulate_rate <= 0.3 THEN 'high' WHEN accumulate_rate <= 0.7 THEN 'mid' ELSE 'low' END car_in_city_level FROM ( SELECT *, LEAD( accumulate_rate, 1 ) over () lead_accumulate_rate FROM ( SELECT MONTH , brand, city, sales, sum( sales ) over ( PARTITION BY MONTH, city ORDER BY sales DESC ) accumulate, sum( sales ) over ( PARTITION BY MONTH, city ) total, sales / sum( sales ) over ( PARTITION BY MONTH, city ) rate, sum( sales ) over ( PARTITION BY MONTH, city ORDER BY sales DESC ) / sum( sales ) over ( PARTITION BY MONTH, city ) accumulate_rate FROM ( SELECT MONTH, brand, city, sum( Sales ) sales FROM cars_insurance_sales GROUP BY MONTH, brand, city ) inner_table ) inner_table ) assist_table """ cursor.execute(query) # 获取查询结果 sql_result = pd.DataFrame(cursor.fetchall()) # 设置字体为 Arial Unicode MS plt.rcParams['font.sans-serif'] = ['Arial Unicode MS'] # 筛选北京22年6月的数据 data = sql_result[sql_result["city"].str.contains("北京")&sql_result["month"].str.contains("2022-06")] # 分别筛选头部、腰部和尾部品牌的数据 top_brands = data[data['cumulative_sales_percentage'] <= 0.3].reset_index(drop=True) middle_brands = data[(data['cumulative_sales_percentage'] > 0.3) & (data['cumulative_sales_percentage'] <= 0.7)].reset_index(drop=True) bottom_brands = data[data['cumulative_sales_percentage'] > 0.7].reset_index(drop=True) # 创建图表 fig, ax = plt.subplots(figsize=(25, 12)) # 绘制条形图 top_bars = ax.bar(top_brands['brand'], top_brands['sales'], color='green', label='Top Brands') middle_bars = ax.bar(middle_brands['brand'], middle_brands['sales'], color='orange', label='Middle Brands') bottom_bars = ax.bar(bottom_brands['brand'], bottom_brands['sales'], color='red', label='Bottom Brands') # 添加数据标签 def add_labels(bars, data_column): for i, bar in enumerate(bars): height = bar.get_height() percentage = data_column[i] ax.text(bar.get_x() + bar.get_width() / 2, height, f'{height} ({percentage*100:.1f}%)', ha='center', va='bottom', rotation='vertical') add_labels(top_bars, top_brands['cumulative_sales_percentage']) add_labels(middle_bars, middlbrands['cumulative_sales_percentage']) add_labels(bottom_bars, bottom_brands['cumulative_sales_percentage']) # 设置图表标题和轴标签 ax.set_title('Top, Middle, and Bottom Brands in beijing') ax.set_xlabel('Brand') ax.set_ylabel('Sales') # 添加图例 ax.legend() # 调整x轴标签的旋转角度和间距 ax.set_xticks(range(len(data['brand']))) ax.set_xticklabels(data['brand'], rotation='vertical', ha='center') # 调整图表布局 plt.tight_layout() # 保存图表 plt.savefig('sales_chart.png', dpi=300) # 显示图表 plt.show()

最终运行结果如下图1-3,可以得到的结论如下

  1. 可以直观的看到北京的头部品牌为比亚迪、特斯拉、一汽大众,腰部品牌为广汽丰田、上汽大众、奥迪、宝马等,尾部品牌广汽埃安、吉利汽车、小鹏、尉来等。以及每个品牌的对应的销量。
  2. 当某个行业发展到一定规模,一定会趋近二八定律(80%的市场份额掌握在20%的玩家手中),汽车市场也是如此,如下图所示总计90个品牌,前20个品牌几乎占据了全北京80%的销量!!!

图1-3

五、数据挖掘

我这里用到的数据挖掘模型是ARIMA模型(差分自回归移动平均模型),是做预测用的,我想看一下目前中国市场上的两个新能源龙头老大(比亚迪和特斯拉)的销量分布是怎样的,并且预测两个品牌下一个月(2023-05)的销量。

import pandas as pd import numpy as np from statsmodels.tsa.arima.model import ARIMA import matplotlib.pyplot as plt sql_result['month'] = pd.to_datetime(sql_result['month']) selected_data = sql_result[(sql_result['month'] >= '2022-06') & (sql_result['month'] <= '2023-05')] # 按品牌过滤数据 byd_data = selected_data[selected_data['brand'] == '比亚迪'] tesla_data = selected_data[selected_data['brand'] == '特斯拉中国'] # 计算比亚迪和特斯拉的月度销量 byd_sales = byd_data.groupby(byd_data['month'].dt.to_period('M'))['sales'].sum().astype(int) tesla_sales = tesla_data.groupby(tesla_data['month'].dt.to_period('M'))['sales'].sum().astype(int) # 创建ARIMA模型对象 model_byd = ARIMA(byd_sales, order=(1, 1, 1)) model_tesla = ARIMA(tesla_sales, order=(1, 1, 1)) # 拟合ARIMA模型 model_byd_fit = model_byd.fit() model_tesla_fit = model_tesla.fit() # 进行未来一个月的销量预测 future_month = pd.to_datetime('2023-05') byd_prediction = model_byd_fit.forecast(steps=1)[0] tesla_prediction = model_tesla_fit.forecast(steps=1)[0] # 可视化图形 fig, ax = plt.subplots(figsize=(12, 6)) # 绘制比亚迪销量 byd_sales.plot(kind='bar', ax=ax, width=0.15, position=0, color='b', label='比亚迪') ax.bar(len(byd_sales), byd_prediction, width=0.2, color='r', label='比亚迪(预测)') # 绘制特斯拉销量 tesla_sales.plot(kind='bar', ax=ax, width=0.15, position=1, color='g', label='特斯拉中国') ax.bar(len(tesla_sales), tesla_prediction, width=0.2, color='y', label='特斯拉中国(预测)') # 添加数据标签 for i, v in enumerate(byd_sales): ax.text(i, v, str(v), ha='center', va='bottom') ax.text(len(byd_sales), byd_prediction, str(int(byd_prediction)), ha='center', va='bottom') for i, v in enumerate(tesla_sales): ax.text(i, v, str(v), ha='center', va='bottom') ax.text(len(tesla_sales), tesla_prediction, str(int(tesla_prediction)), ha='center', va='bottom') # 设置图形属性 plt.xlabel('Month') plt.ylabel('Sales') plt.title('Monthly Sales Comparison') plt.xticks(range(len(byd_sales.index) + 1), [d.strftime('%Y-%m') for d in byd_sales.index] + [future_month.strftime('%Y-%m')], rotation=45) plt.legend() # 保存图表为图片文件 plt.savefig('Monthly_sales_comparison.png', dpi=300) # 显示图形 plt.show()

运行结果如下图1-4:历史每个月份比亚迪销量都比特斯拉销量高,且差距越来越大,模型预测最新5月的销量同样也是远远领先于特斯拉,比亚迪 国民的骄傲~

另附上我的个人观点:我承认马斯克的特斯拉很酷,但是在中国的市场,不是人人都是特斯拉的受众, 就算频繁的降价但对于大多数中国家庭来说价格还是很高,汽车本就是一款低频重决策的大件产品,如果受众用户不是全部群体会很难再铺开市场,小道消息称特斯拉今年会上市一款平民版本,售价在10W以内,若真的上市,那市场份额就很难预估了,没准还会短暂的打破二八定律也说不准 !!!

图1-4

END