说实话,我刚入行那会儿,面对Excel里几万行跑不动的数据,心里那个慌啊。直到我遇见了Python的数据分析三剑客——Pandas、NumPy和Matplotlib,整个世界都变了。今天我想跟你聊聊,怎么用这三样东西,把你手头那些乱成一团麻的数据,变成能直接汇报给老板看的精美图表和洞察。
先别急着写代码,把环境搭舒服了
很多新手一上来就蹦到代码里,结果因为版本冲突、包没装对,折腾半天连个Hello World都跑不出来,心态直接崩了。听我一句劝,先把地基打牢。
我强烈建议你用conda或者venv搞一个独立的环境。比如你现在打开终端,敲这几行:
# 创建一个名叫data_env的环境,Python版本3.10很稳
conda create -n data_env python=3.10
conda activate data_env
# 装核心三件套,顺手把jupyter也装了,写代码更有感觉
pip install pandas numpy matplotlib jupyterlab
如果你用的是VS Code或者PyCharm,记得把解释器指向这个环境。别问为什么,问就是以前我因为环境混用,导了半天的库结果找不到,差点把电脑砸了。装完之后,咱们写个最简单的测试脚本,确认它们都能跑起来:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
print(f"Pandas版本: {pd.__version__}")
print(f"NumPy版本: {np.__version__}")
print("环境搭建成功,咱们开始干活!")
看到输出版本号,心里那块石头就落地了。
NumPy:给数据找个靠谱的“容器”
Pandas虽然好使,但它底层其实赖着NumPy吃饭。你不学NumPy,遇到稍微复杂点的向量化运算,就得写循环,那性能差得离谱。
NumPy的核心是** ndarray**,你可以把它想象成一个超级能干的Excel表格,但它支持数学运算。比如,你想算一周的气温平均值,用普通列表你得写个循环,用NumPy,一行搞定:
import numpy as np
# 模拟一周气温数据
temps = np.array([22, 23, 21, 25, 24, 20, 19])
# 向量化运算:所有温度加2度(比如换算成华氏度简化版)
temps_scaled = temps * 1.8 + 32
print(f"原始气温: {temps}")
print(f"换算后: {temps_scaled}")
# 更常见的场景:随机生成1000个正态分布数据,模拟用户年龄
ages = np.random.normal(loc=35, scale=10, size=1000)
# 年龄不能是负数,也不能超过120,简单的过滤
ages = ages[(ages > 0) & (ages < 120)]
print(f"生成用户年龄样本: 最小{ages.min()}, 最大{ages.max()}, 平均{ages.mean():.2f}")
你看,np.random.normal这一行,比你在Excel里拉1000个随机数快得多。而且在Pandas里,你经常会碰到np.where、np.isnan这些函数,它们是解决数据缺失和条件填充的神器。
Pandas:真正让你“起飞”的数据处理库
如果说NumPy是引擎,那Pandas就是整辆车。它是做数据分析的核心,80%的时间你都在跟DataFrame打交道。
1. 读入数据,先别急着看全貌
假设你手里有一份电商订单数据orders.csv,里面可能有几万行。别一上来就用print(df),会卡死你的终端。
import pandas as pd
# 读取数据
df = pd.read_csv('orders.csv')
# 查看前5行,看看数据长啥样
print(df.head())
# 核心指标快速扫描
print(df.info()) # 看列名、非空数量、数据类型
print(df.describe()) # 数值列的统计描述:均值、标准差、四分位数
print(df.shape) # 行数和列数
这一步叫数据概览,能帮你快速判断数据质量。比如info()里如果某列Non-Null Count远小于总行数,说明缺失值很多,后面得重点处理。
2. 清洗数据:这才是真正费功夫的地方
现实中的数据,脏得一塌糊涂。空值、重复行、格式错误、异常值……
处理缺失值:
# 方法一:直接删掉缺失严重的行(如果数据量够大)
df_clean = df.dropna()
# 方法二:填充缺失值。比如年龄缺失,用中位数填充,比均值更抗干扰
df['age'] = df['age'].fillna(df['age'].median())
# 方法三:如果是订单金额,空值可能意味着没成交,那就填0
df['order_amount'] = df['order_amount'].fillna(0)
处理重复值:
# 查看有多少重复行
print(df.duplicated().sum())
# 删除重复行,保留第一条
df = df.drop_duplicates()
数据类型转换:
# 把字符串日期变成datetime对象,这一步不做,后面分组统计全是乱码
df['order_date'] = pd.to_datetime(df['order_date'])
# 把金额列强制转为数值,遇到无法转换的报错,这能帮你揪出坏数据
df['price'] = pd.to_numeric(df['price'], errors='coerce')
3. 数据筛选与分组:透视表是神器
老板问:“上个月华东地区的销售额是多少?” 你不用一个个去翻,用groupby和透视表:
# 筛选:只看2023年,且金额大于100的订单
filtered_df = df[(df['order_date'].dt.year == 2023) & (df['amount'] > 100)]
# 分组汇总:按地区和销售员统计销售额
summary = filtered_df.groupby(['region', 'salesperson'])['amount'].agg(['sum', 'mean', 'count'])
summary.columns = ['总销售额', '平均订单额', '订单数']
print(summary.sort_values('总销售额', ascending=False))
这比你在Excel里拉透视表还快,而且数据更新后,代码重跑一遍就行,不用手动操作。
Matplotlib & Seaborn:让数据“说话”
分析完数据,你得把它展示出来。纯数字没人爱看,图表才是王道。
1. 基础绘图:折线图看趋势
假设你要看过去30天的销售走势:
import matplotlib.pyplot as plt
# 设置中文字体,避免乱码(Windows用户可能需要指定具体字体路径)
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 假设你有一个按日期汇总的数据
daily_sales = df.groupby(df['order_date'].dt.date)['amount'].sum()
plt.figure(figsize=(12, 6))
plt.plot(daily_sales.index, daily_sales.values, marker='o', linestyle='-', color='#1f77b4')
plt.title('近30天销售趋势图')
plt.xlabel('日期')
plt.ylabel('销售额')
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
2. 进阶可视化:用Seaborn画分布和关系
Seaborn是基于Matplotlib的封装,画统计图表更简单、更好看。
import seaborn as sns
# 画一个销售额的分布图,看看是不是正态分布
plt.figure(figsize=(10, 5))
sns.histplot(df['amount'], bins=30, kde=True, color='skyblue')
plt.title('订单金额分布')
plt.show()
# 画一个散点图,看看广告投入和销售额有没有关系
plt.figure(figsize=(10, 6))
sns.scatterplot(data=df, x='ad_spend', y='sales', hue='region', style='region')
plt.title('广告投入 vs 销售额(按地区区分)')
plt.show()
一个完整的真实案例:分析电商用户复购行为
光说不练假把式。我们来模拟一个真实的业务场景:如何识别高价值复购用户?
假设你拿到了一份用户交易记录表,里面包含:user_id, order_date, amount, product_category。
第一步:数据读取与初步清洗
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 读取数据
df = pd.read_csv('user_transactions.csv')
# 查看基本信息
print(df.head())
print(df.info())
# 转换日期
df['order_date'] = pd.to_datetime(df['order_date'])
# 去除金额异常值(比如金额为0或负数,可能是测试数据)
df = df[df['amount'] > 0]
第二步:计算用户行为指标
我们需要算出每个用户的几个关键指标:首次购买时间、最近一次购买时间、购买次数、总消费金额。
# 按用户分组,计算各项指标
user_stats = df.groupby('user_id').agg(
first_order=('order_date', 'min'),
last_order=('order_date', 'max'),
order_count=('order_date', 'count'),
total_spend=('amount', 'sum'),
avg_order_value=('amount', 'mean')
).reset_index()
# 计算RFM指标中的M(Monetary)和F(Frequency)
# R(Recency):距离今天的天数
today = df['order_date'].max()
user_stats['recency'] = (today - user_stats['last_order']).dt.days
print(user_stats.head())
第三步:用户分层(RFM模型简化版)
我们想找出“高价值活跃用户”。这里用简单的百分位切割:
# 给Recency, Frequency, Monetary打分(1-5分)
# 注意:Recency越小越好,Frequency和Monetary越大越好
user_stats['R_score'] = pd.qcut(user_stats['recency'], q=5, labels=[5,4,3,2,1])
user_stats['F_score'] = pd.qcut(user_stats['order_count'], q=5, labels=[1,2,3,4,5])
user_stats['M_score'] = pd.qcut(user_stats['total_spend'], q=5, labels=[1,2,3,4,5])
# 综合得分
user_stats['segment_score'] = user_stats['R_score'].astype(int) + \
user_stats['F_score'].astype(int) + \
user_stats['M_score'].astype(int)
# 定义用户类型
def define_segment(row):
if row['segment_score'] >= 12:
return '高价值用户'
elif row['segment_score'] >= 8:
return '潜力用户'
elif row['recency'] > 180: # 超过半年没买
return '流失用户'
else:
return '普通用户'
user_stats['user_segment'] = user_stats.apply(define_segment, axis=1)
第四步:可视化分析结果
看看各用户类型的分布情况:
plt.figure(figsize=(12, 5))
# 图1:用户类型分布饼图
plt.subplot(1, 2, 1)
segment_counts = user_stats['user_segment'].value_counts()
colors = ['#ff9999','#66b3ff','#99ff99','#ffcc99']
plt.pie(segment_counts.values, labels=segment_counts.index, autopct='%1.1f%%', colors=colors)
plt.title('用户分层分布')
# 图2:各用户类型的平均订单金额对比
plt.subplot(1, 2, 2)
segment_avg_spend = user_stats.groupby('user_segment')['avg_order_value'].mean()
segment_avg_spend.plot(kind='bar', color='skyblue')
plt.title('各用户类型平均订单金额')
plt.ylabel('平均金额')
plt.xticks(rotation=45)
plt.tight_layout()
plt.show()
第五步:输出 actionable insights(可落地的建议)
这时候,你可以直接拿着这个分析结果去汇报:
- “高价值用户占比15%,但贡献了60%的营收,建议提供VIP专属客服。”
- “流失用户占比20%,建议触发召回短信或优惠券。”
- “潜力用户数量最大,是本次618大促的重点转化对象。”
避坑指南:这些错误我替你犯过了
- 不要在整个DataFrame上循环:Python的
for循环处理大数据极慢。能用apply、groupby、vectorization(向量化)就别用循环。 - 内存管理:处理几GB的数据时,注意列的数据类型。比如
category列如果只有几个固定值,用category类型而不是object,能省大量内存。 - 缺失值不要盲目删除:先分析缺失原因。如果是随机缺失,可以填充;如果是系统性缺失(比如某字段只有部分人填),得想办法补全或剔除。
- 图表不要花里胡哨:颜色不要超过5种,去除不必要的网格线、边框(Snhorn的
despine()很好用),把重点放在数据本身。
总结
从NumPy的底层运算,到Pandas的灵活处理,再到Matplotlib的直观展示,这套组合拳打下来,你基本能应对80%的日常数据分析需求。记住,工具只是手段,理解业务、提出假设、验证结论才是数据分析的核心。
别光看,动手敲代码。把你手边那份乱七八糟的Excel,用Python重新跑一遍,你会回来感谢我的。加油!
