☰
数据挖掘分析基础:函数计算、基本绘图与透视分析实战
2026/10/15 9:55:17 网站建设 项目流程

1. 数据挖掘分析基础的整体设计思路

1.1 为什么从函数计算和基础绘图切入

很多人一上来就想着搞机器学习模型、上深度学习框架,结果连数据长什么样都没看清楚。我做了这么多年数据分析,最深的体会就是:数据挖掘的地基不是算法,而是你对数据的感知能力。函数计算、基本绘图、透视分析这三样东西,看起来简单,实际上决定了你后续所有分析工作的上限。

打个比方,这就像学做菜。你可以直接去买预制菜包,但如果你连食材新不新鲜、火候够不够都判断不了,那永远只能依赖别人配好的料包。函数计算就是你的刀工,基本绘图是你的摆盘和观察,透视分析是你对食材搭配的理解。这三样练好了,后面不管是做回归预测还是聚类分群,你心里都有底。

这套分析基础适合什么人?我总结了三类:第一类是刚入行的数据分析新手,需要一套能直接上手的方法论;第二类是有一定Excel基础但想转向代码分析的职场人;第三类是做业务运营、市场研究的同学,需要用数据支撑决策但不想被技术门槛卡住。不管你属于哪一类,接下来的内容都会从最实际的操作出发,把每个环节讲透。

1.2 分析流程的四个核心环节

我把整个数据挖掘的分析基础拆成四个环节,每个环节都有明确的目标和产出物:

  • 数据接入与清洗:把原始数据变成可分析的干净表格,处理缺失值、异常值、格式转换
  • 函数计算与特征衍生:用聚合、分组、条件计算等方式,从原始字段中提取有价值的新指标
  • 可视化探索:通过基本绘图函数快速发现分布规律、趋势变化和异常点
  • 透视分析与交叉验证:用多维透视表做交叉分析,验证假设并发现隐藏关联

这四个环节不是线性的,实际工作中经常需要来回迭代。比如你在绘图时发现某个字段有异常聚集,就得回到清洗环节重新处理;在透视分析时发现某个维度缺失,又要回到特征衍生环节补充计算。这种迭代思维比死守流程重要得多。

注意:不要试图一次性把所有数据都清洗完美再开始分析。我见过太多人卡在数据清洗阶段,花了80%的时间处理边角问题,结果真正有价值的分析没做多少。建议先快速清洗一版能用的数据,边分析边完善。

2. 函数计算的核心方法与实操要点

2.1 聚合函数:从明细到汇总的第一步

聚合函数是数据挖掘中最基础也最常用的工具。简单说,就是把多行数据按照某个维度压缩成一行,同时计算出统计量。常见的聚合操作包括求和、均值、计数、最大值、最小值、标准差等。

我拿一个模拟的零售数据集来举例。假设你有一张销售明细表,包含日期、门店、品类、销售额、销量这几个字段。你想知道每个门店的总销售额和平均客单价,这时候就需要用到分组聚合。

在Python的pandas里,核心代码就一行:

import pandas as pd # 模拟数据 df = pd.DataFrame({ '日期': ['2024-01-01', '2024-01-01', '2024-01-02', '2024-01-02', '2024-01-03'], '门店': ['A店', 'B店', 'A店', 'B店', 'A店'], '品类': ['饮料', '零食', '饮料', '饮料', '零食'], '销售额': [1200, 800, 1500, 950, 1100], '销量': [100, 60, 130, 80, 90] }) # 按门店分组聚合 result = df.groupby('门店').agg( 总销售额=('销售额', 'sum'), 平均销售额=('销售额', 'mean'), 总销量=('销量', 'sum'), 订单数=('销售额', 'count') ).reset_index() print(result)

这段代码的输出会告诉你每个门店的总销售额、平均每笔销售额、总销量和订单数量。看起来简单,但这里面有几个实操细节值得注意。

第一,聚合后的索引处理。groupby之后默认会把分组字段变成索引,如果你后续还要做合并或者导出,记得用reset_index()把索引还原成列。这个小细节坑过很多人,尤其是从SQL转过来的同学,习惯了结果集就是表格,容易忽略索引问题。

第二,多维度聚合的写法。如果你想同时按门店和品类两个维度聚合,只需要在groupby里传入列表:

result_multi = df.groupby(['门店', '品类']).agg( 总销售额=('销售额', 'sum'), 平均销售额=('销售额', 'mean') ).reset_index()

这样得到的就是门店和品类的交叉汇总,每个门店的每个品类单独一行。这种多维聚合在后续做透视分析时非常有用,相当于提前把数据整理成了透视表的格式。

第三,自定义聚合函数。除了内置的sum、mean、count,你还可以传入自定义函数。比如你想计算每个门店销售额的中位数绝对偏差,或者计算销售额的变异系数:

import numpy as np def cv(x): return np.std(x) / np.mean(x) if np.mean(x) != 0 else 0 result_custom = df.groupby('门店').agg( 总销售额=('销售额', 'sum'), 变异系数=('销售额', cv) ).reset_index()

变异系数这个指标在实际业务中很有用,它衡量的是数据的离散程度相对于均值的大小。变异系数越大,说明这个门店的销售波动越剧烈,可能需要重点关注。

2.2 条件计算:用函数实现灵活的数据筛选与衍生

条件计算是函数计算中最能体现分析功力的部分。所谓条件计算,就是根据某些判断条件,对数据进行筛选、分类或衍生新字段。

最常用的场景是分箱。比如你想把销售额分成高、中、低三档,可以用numpy的where或者pandas的cut函数:

# 方法一:用np.where做条件判断 df['销售等级'] = np.where(df['销售额'] >= 1200, '高', np.where(df['销售额'] >= 900, '中', '低')) # 方法二:用pd.cut做等距分箱 df['销售额分箱'] = pd.cut(df['销售额'], bins=3, labels=['低', '中', '高']) # 方法三:用pd.qcut做等频分箱 df['销售额等频分箱'] = pd.qcut(df['销售额'], q=3, labels=['低', '中', '高'])

这三种方法各有适用场景。np.where适合自定义阈值,pd.cut适合等距划分,pd.qcut适合等频划分。我个人的经验是,业务指标的分箱优先用np.where,因为业务阈值往往有实际含义(比如销售额1200以上算大客户),而不是机械地等分。

条件计算还有一个高频场景是条件聚合。比如你想统计每个门店中饮料品类的销售额占比:

# 先计算每个门店的总销售额 total = df.groupby('门店')['销售额'].sum().rename('门店总销售额') # 再计算每个门店饮料品类的销售额 drink = df[df['品类'] == '饮料'].groupby('门店')['销售额'].sum().rename('饮料销售额') # 合并并计算占比 ratio = pd.concat([total, drink], axis=1).fillna(0) ratio['饮料占比'] = ratio['饮料销售额'] / ratio['门店总销售额'] print(ratio)

这种先分组再合并的思路,在处理复杂业务指标时非常常见。关键是要理清楚每个中间结果的粒度和含义,避免在合并时出现数据错位。

2.3 窗口函数:让数据在时间轴上动起来

窗口函数是函数计算中进阶但极其重要的部分。它允许你在不改变数据行数的情况下,计算基于某个窗口范围的统计量。最典型的应用就是计算累计值、移动平均和同比环比。

假设你有一张按日期排列的销售数据,你想计算每天的累计销售额和7天移动平均:

# 按日期排序 df_sorted = df.sort_values('日期').reset_index(drop=True) # 计算累计销售额 df_sorted['累计销售额'] = df_sorted['销售额'].cumsum() # 计算7天移动平均(这里用3天模拟,因为数据量少) df_sorted['移动平均'] = df_sorted['销售额'].rolling(window=3, min_periods=1).mean() # 计算环比增长率 df_sorted['环比增长率'] = df_sorted['销售额'].pct_change() print(df_sorted)

窗口函数的核心参数是window,它决定了计算的范围。window=3表示包含当前行在内的前3行。min_periods=1表示即使窗口内数据不足3行也进行计算,避免开头出现NaN。

在实际业务中,移动平均常用来平滑短期波动,发现长期趋势。比如你分析日活用户数,单日的波动可能受各种因素影响,但7天移动平均就能看出真实的增长或下降趋势。

实操心得:窗口函数在计算时一定要注意数据的排序。如果数据没有按时间排序,rolling的结果就是错的。我建议在计算窗口函数之前,先显式地做一次sort_values,并且用reset_index(drop=True)重置索引,避免后续操作出现索引对齐问题。

3. 基本绘图函数的实战应用

3.1 为什么可视化是数据挖掘的"眼睛"

我一直跟团队里的新人说:你画不出图,就说明你还没理解数据。可视化不只是为了做报告好看,更重要的是在分析过程中帮你快速发现规律、验证假设、定位问题。

基本绘图函数不需要多复杂,matplotlib和seaborn的基础功能就足够覆盖80%的日常分析需求。关键是要知道什么场景用什么图。

我整理了一个快速对照表:

分析目的推荐图表核心函数
看单变量分布直方图、箱线图plt.hist()、plt.boxplot()
看两个变量关系散点图plt.scatter()
看时间趋势折线图plt.plot()
看类别对比柱状图plt.bar()
看占比结构饼图、堆叠柱状图plt.pie()、plt.bar(stacked=True)
看多变量相关性热力图sns.heatmap()

这张表建议存下来,每次分析前先想清楚你要回答什么问题,再选对应的图。

3.2 分布分析:直方图与箱线图的组合拳

分布分析是数据探索的第一步。你需要知道数据集中在哪个范围、有没有异常值、分布是对称还是偏斜。

直方图看整体形态,箱线图看异常值和四分位距,两个结合起来用效果最好:

import matplotlib.pyplot as plt import seaborn as sns # 设置中文字体 plt.rcParams['font.sans-serif'] = ['SimHei'] plt.rcParams['axes.unicode_minus'] = False fig, axes = plt.subplots(1, 2, figsize=(12, 5)) # 直方图 axes[0].hist(df['销售额'], bins=10, edgecolor='black', alpha=0.7) axes[0].set_title('销售额分布直方图') axes[0].set_xlabel('销售额') axes[0].set_ylabel('频数') # 箱线图 axes[1].boxplot(df['销售额']) axes[1].set_title('销售额箱线图') axes[1].set_ylabel('销售额') plt.tight_layout() plt.show()

直方图的bins参数很关键。bins太少,分布形态看不清楚;bins太多,图形会变得毛刺。我的经验是,数据量在100以内用5-8个bins,100-1000用10-20个bins,1000以上用20-50个bins。当然这不是绝对的,你可以多试几个值,找到最能说明问题的那个。

箱线图主要看几个东西:中位数线的位置、箱体的高度(四分位距)、须的长度、以及须外面的点(异常值)。如果箱体很扁、须很长,说明数据离散程度大;如果中位数不在箱体中间,说明分布偏斜。

3.3 关系分析:散点图与相关性热力图

当你怀疑两个变量之间存在关联时,散点图是最直观的工具。比如你想看广告投入和销售额之间的关系:

# 散点图 plt.figure(figsize=(8, 6)) plt.scatter(df['广告投入'], df['销售额'], alpha=0.6, edgecolors='white') plt.xlabel('广告投入') plt.ylabel('销售额') plt.title('广告投入与销售额关系散点图') # 添加趋势线 z = np.polyfit(df['广告投入'], df['销售额'], 1) p = np.poly1d(z) plt.plot(df['广告投入'], p(df['广告投入']), 'r--', alpha=0.8, label='趋势线') plt.legend() plt.show()

散点图能告诉你三件事:有没有关系(点是否聚集在一条线附近)、关系是正是负(趋势线向上还是向下)、关系是线性还是非线性(点是否弯曲分布)。

如果变量比较多,散点图矩阵或者相关性热力图更高效:

# 相关性热力图 plt.figure(figsize=(10, 8)) corr_matrix = df[['销售额', '销量', '广告投入', '客流量']].corr() sns.heatmap(corr_matrix, annot=True, cmap='RdBu_r', center=0, fmt='.2f', square=True, linewidths=0.5) plt.title('变量相关性热力图') plt.show()

热力图的颜色越深,相关性越强。红色代表正相关,蓝色代表负相关。annot=True会把相关系数标在格子里,方便直接读数。一般来说,相关系数绝对值大于0.7算强相关,0.3到0.7算中等相关,小于0.3算弱相关。

注意:相关性不等于因果性。两个变量高度相关,可能是因为它们都受第三个变量影响,也可能只是巧合。热力图只是帮你发现线索,真正的因果关系需要业务逻辑和实验验证。

3.4 趋势分析:折线图与多轴图的技巧

时间序列数据离不开折线图。但折线图有个常见问题:如果多个指标的数值范围差异很大,画在一起会有一条线被压扁。这时候需要用双轴图:

fig, ax1 = plt.subplots(figsize=(12, 6)) # 左轴:销售额 ax1.plot(df_sorted['日期'], df_sorted['销售额'], 'b-o', label='销售额') ax1.set_xlabel('日期') ax1.set_ylabel('销售额', color='b') ax1.tick_params(axis='y', labelcolor='b') # 右轴:增长率 ax2 = ax1.twinx() ax2.plot(df_sorted['日期'], df_sorted['环比增长率'], 'r-s', label='环比增长率') ax2.set_ylabel('环比增长率', color='r') ax2.tick_params(axis='y', labelcolor='r') plt.title('销售额与环比增长率趋势图') fig.tight_layout() plt.show()

双轴图的关键是颜色对应:左轴的数据用蓝色,右轴的数据用红色,坐标轴标签和刻度也对应颜色,这样读者一眼就能分清哪条线对应哪个轴。

另外,折线图的x轴如果是日期,建议把日期转成datetime类型,这样matplotlib会自动优化刻度显示,避免日期标签重叠。

4. 透视分析与交叉验证的实操方法

4.1 透视表:多维分析的瑞士军刀

透视表是数据挖掘中最实用的工具之一。它允许你快速地在不同维度之间切换视角,发现数据中的模式和异常。

pandas的pivot_table函数功能非常强大,核心参数有四个:

  • values:要聚合的数值列
  • index:行维度
  • columns:列维度
  • aggfunc:聚合函数
# 基础透视表:门店为行,品类为列,销售额求和 pivot_basic = pd.pivot_table( df, values='销售额', index='门店', columns='品类', aggfunc='sum', fill_value=0, margins=True, # 添加总计行和列 margins_name='总计' ) print(pivot_basic)

margins=True会自动添加总计行和列,这在做汇总报告时非常方便。fill_value=0把缺失值填充为0,避免出现NaN影响后续计算。

透视表最强大的地方在于多级索引和多级列。你可以在index和columns里传入列表,实现多层交叉:

# 多级透视表 pivot_multi = pd.pivot_table( df, values='销售额', index=['门店', '品类'], columns='日期', aggfunc='sum', fill_value=0 ) print(pivot_multi)

这样得到的就是门店-品类-日期三个维度的交叉表。虽然看起来有点复杂,但在分析多因素影响时非常有用。

4.2 交叉验证:用透视表验证业务假设

透视分析不只是做汇总,更重要的是验证假设。我举个实际例子。

假设你怀疑:A店的饮料销售额比B店高,是因为A店的客流量更大,而不是因为A店的饮料更受欢迎。这时候你可以做两个透视表来验证:

# 透视表1:各门店各品类的销售额 pivot_sales = pd.pivot_table(df, values='销售额', index='门店', columns='品类', aggfunc='sum') # 透视表2:各门店各品类的客流量 pivot_traffic = pd.pivot_table(df, values='客流量', index='门店', columns='品类', aggfunc='sum') # 计算单位客流量的销售额(效率指标) pivot_efficiency = pivot_sales / pivot_traffic print("各门店各品类的单位客流量销售额:") print(pivot_efficiency)

如果A店的饮料销售额高,但单位客流量销售额和B店差不多,那就说明差异主要来自客流量,而不是饮料的吸引力。如果A店的单位客流量销售额也明显更高,那才说明A店的饮料确实更受欢迎。

这种先看总量、再看效率的分析思路,在业务分析中非常实用。总量指标容易被规模因素干扰,效率指标才能反映真实的竞争力。

4.3 透视表的进阶技巧:自定义聚合与多指标展示

pivot_table的aggfunc参数可以传入字典,实现不同列用不同聚合方式:

pivot_custom = pd.pivot_table( df, values=['销售额', '销量'], index='门店', columns='品类', aggfunc={'销售额': 'sum', '销量': 'mean'}, fill_value=0 ) print(pivot_custom)

这样销售额用求和,销量用均值,一张表里展示两种不同的统计量。

如果你想要更复杂的自定义聚合,可以先把聚合结果算好,再用pivot或者unstack来重塑:

# 先分组计算多个指标 grouped = df.groupby(['门店', '品类']).agg( 总销售额=('销售额', 'sum'), 平均销售额=('销售额', 'mean'), 订单数=('销售额', 'count') ).reset_index() # 再用pivot重塑 pivot_final = grouped.pivot(index='门店', columns='品类', values='总销售额') print(pivot_final)

这种先聚合再重塑的方式更灵活,适合处理复杂的业务指标计算。

实操心得:透视表在数据量大的时候可能会比较慢。如果数据超过10万行,建议先用groupby做预聚合,再对聚合后的结果做透视。另外,pivot_table默认会丢弃包含NaN的行,如果不想丢弃,记得设置dropna=False。

5. 常见问题与排查技巧实录

5.1 函数计算中的典型报错与解决

在实际操作中,函数计算环节最容易遇到以下几类问题:

问题一:SettingWithCopyWarning

这个警告几乎每个pandas用户都遇到过。它出现的原因是你在一个切片数据上做修改,pandas不确定你是想修改原始数据还是副本。

# 错误示范 df[df['销售额'] > 1000]['等级'] = '高' # 会触发警告 # 正确做法 df.loc[df['销售额'] > 1000, '等级'] = '高'

解决方案很简单:用loc做条件赋值,或者先copy一份数据再操作。我个人的习惯是,只要涉及条件修改,一律用loc,既安全又清晰。

问题二:聚合后数据行数不对

有时候你groupby之后发现行数比预期少,通常是因为分组字段里有NaN值。pandas默认会丢弃分组字段为NaN的行。如果不想丢弃,设置dropna=False:

df.groupby('门店', dropna=False)['销售额'].sum()

问题三:数据类型不匹配导致计算错误

比如销售额字段是字符串类型,做sum的时候会拼接而不是求和。这时候需要先转换类型:

df['销售额'] = pd.to_numeric(df['销售额'], errors='coerce')

errors='coerce'会把无法转换的值变成NaN,避免报错中断。转换后再检查一下有多少NaN,决定是填充还是删除。

5.2 绘图中的中文显示与样式调整

matplotlib默认不支持中文,如果不设置字体,中文会显示成方框。解决方案:

plt.rcParams['font.sans-serif'] = ['SimHei'] # Windows系统 # plt.rcParams['font.sans-serif'] = ['Arial Unicode MS'] # Mac系统 plt.rcParams['axes.unicode_minus'] = False # 解决负号显示问题

这两行代码建议放在所有绘图代码的最前面。另外,如果觉得默认样式太丑,可以用seaborn的样式:

sns.set_style("whitegrid") # 白色网格背景 sns.set_palette("husl") # 设置配色方案

5.3 透视表结果不达预期的排查清单

透视表出问题时,按以下顺序排查:

排查项检查内容解决方法
数据行数透视后行数是否合理检查index字段是否有NaN,设置dropna=False
数值列values字段是否为数值类型用pd.to_numeric转换
聚合函数aggfunc是否适用该数据类型数值用sum/mean,文本用count
缺失值fill_value是否设置设置fill_value=0或合适值
列顺序columns字段的排序用reindex调整列顺序
多级索引是否需要扁平化用reset_index()或droplevel()

这张表建议截图保存,下次遇到透视表问题直接对照排查,能省不少时间。

5.4 分析流程中的避坑经验

最后分享几条我在实际项目中踩过的坑:

第一,不要忽略数据的时间范围。有一次我做销售分析,发现某门店销售额异常高,排查了半天才发现那家店的数据包含了整整两年的记录,而其他店只有一年。分析前一定要确认每个分组的时间范围是否一致。

第二,聚合前先检查重复值。如果明细表里有重复记录,聚合结果会偏大。用df.duplicated().sum()快速检查,必要时用drop_duplicates()去重。

第三,透视表的margins行/列要慎用。margins计算的是所有行的汇总,但如果你的数据本身已经是聚合过的,margins可能会重复计算。建议只在明细数据上使用margins。

第四,绘图前先做数据采样。如果数据量超过10万行,散点图会变得非常卡顿,而且点重叠严重看不出规律。建议随机采样5000-10000行来绘图,或者用hexbin图替代散点图。

第五,养成保存中间结果的习惯。每完成一个关键步骤,就把结果保存成CSV或pickle文件。这样如果后续步骤出错,不用从头再来。我通常会在清洗后、特征衍生后、透视分析后各保存一次。

这套分析基础看起来都是些简单工具,但真正把每个环节做扎实,你会发现后续无论做什么复杂分析,心里都有清晰的路径。函数计算让你能灵活加工数据,基本绘图让你能直观感知数据,透视分析让你能多维验证假设。这三样练熟了,数据挖掘的门就算真正入了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询