开篇:当你掌握Pandas,世界就不同了
2023年秋天,我的朋友李明(某新能源品牌区域运营经理)给我打电话,声音里满是兴奋:
"你知道吗?我今天用Pandas处理了30个门店、3个月的数据,只用了5分钟。以前用Excel,光打开文件、复制粘贴就要2小时。我现在终于理解你说的'思维跃迁'是什么意思了。"
什么是思维跃迁?
在Excel时代,你的思维是:
- "我要打开这个文件"
- "我要找到这一列"
- "我要复制粘贴到那个表格"
- "我要用鼠标拖一个公式"
在Pandas时代,你的思维是:
- "我要读取所有数据"
- "我要筛选符合条件的数据"
- "我要按门店分组统计"
- "我要生成可视化图表"
从操作细节到业务逻辑,这就是思维的跃迁。
什么是Pandas?
官方定义
Pandas = Panel Datas 的缩写(面板数据的缩写)
Pandas是Python中最强大的数据分析库,专门用来处理结构化数据(表格数据)。
通俗理解
Pandas就是Python版的Excel,但比Excel强大100倍。
它可以:
- 像Excel一样读取、查看、编辑表格数据
- 但速度更快(处理百万行数据也不卡)
- 但功能更强(复杂数据分析一行代码搞定)
- 但更灵活(可以自动化、批量化处理)
为什么运营专家需要Pandas?
真实场景1:月度数据汇总
Excel方式:
- 打开30个门店的Excel文件(10分钟)
- 逐个复制数据到汇总表(30分钟)
- 检查数据格式,修正错误(20分钟)
- 制作数据透视表(15分钟)
- 总计:75分钟
Pandas方式:
import pandas as pd
import glob
# 读取所有文件并合并
files = glob.glob('门店数据/*.xlsx')
df = pd.concat([[pd.read](http://pd.read)_excel(f) for f in files])
# 生成数据透视表
pivot = df.pivot_table(values='营收', index='门店', columns='月份', aggfunc='sum')
[pivot.to](http://pivot.to)_excel('月度汇总.xlsx')
- 总计:5分钟(含运行时间)
真实场景2:数据清洗
某品牌从系统导出的客户数据有很多问题:
- 电话号码格式不统一
- 有重复客户记录
- 有缺失值
- 日期格式混乱
用Excel手工清洗,需要1天时间。
用Pandas,10分钟搞定。
Pandas的核心概念
1. DataFrame — Pandas的核心
DataFrame是什么?
简单说,DataFrame就是一个表格,和Excel的工作表一模一样。
import pandas as pd
# 创建一个DataFrame
门店数据 = pd.DataFrame({
'门店': ['北京朝阳店', '上海浦东店', '深圳南山店'],
'NPS': [85.6, 92.3, 78.9],
'营收': [1250000, 1580000, 980000],
'工单数': [800, 950, 620]
})
print(门店数据)
输出:
门店 NPS 营收 工单数
0 北京朝阳店 85.6 1250000 800
1 上海浦东店 92.3 1580000 950
2 深圳南山店 78.9 980000 620
关键概念:
- 行(Row):每一行是一条记录(一家门店)
- 列(Column):每一列是一个属性(NPS、营收等)
- 索引(Index):左边的0、1、2是行索引
2. Series — DataFrame的一列
Series是什么?
Series就是DataFrame的一列,可以理解为一个列表。
# 提取一列
NPS列 = 门店数据['NPS']
print(NPS列)
print(type(NPS列)) # <class 'pandas.core.series.Series'>
输出:
0 85.6
1 92.3
2 78.9
Name: NPS, dtype: float64
第一部分:数据读取
1. 读取Excel文件
最常用的操作:
import pandas as pd
# 读取Excel文件
df = [pd.read](http://pd.read)_excel('门店数据.xlsx')
# 查看前5行
print(df.head())
# 查看后5行
print(df.tail())
# 查看数据形状(多少行、多少列)
print(df.shape) # 输出:(100, 8) 表示100行8列
# 查看列名
print(df.columns)
# 查看数据类型
print(df.dtypes)
# 查看基本统计信息
print(df.describe())
读取指定工作表:
# 读取第二个工作表
df = [pd.read](http://pd.read)_excel('门店数据.xlsx', sheet_name=1)
# 或指定工作表名称
df = [pd.read](http://pd.read)_excel('门店数据.xlsx', sheet_name='2024年数据')
# 读取多个工作表
xls = pd.ExcelFile('门店数据.xlsx')
df1 = [pd.read](http://pd.read)_excel(xls, '1月')
df2 = [pd.read](http://pd.read)_excel(xls, '2月')
2. 读取CSV文件
# 读取CSV文件
df = [pd.read](http://pd.read)_csv('门店数据.csv')
# 指定编码(处理中文)
df = [pd.read](http://pd.read)_csv('门店数据.csv', encoding='utf-8')
# 或
df = [pd.read](http://pd.read)_csv('门店数据.csv', encoding='gbk')
3. 实战案例:批量读取多个文件
import pandas as pd
import glob
# 读取文件夹下所有Excel文件
files = glob.glob('门店数据/*.xlsx')
# 方法1:逐个读取并合并
df_list = []
for file in files:
df_temp = [pd.read](http://pd.read)_excel(file)
df_temp['文件名'] = file # 添加来源标记
df_list.append(df_temp)
df_all = pd.concat(df_list, ignore_index=True)
print(f"共读取了{len(files)}个文件,{len(df_all)}条数据")
# 方法2:一行代码搞定
df_all = pd.concat([[pd.read](http://pd.read)_excel(f) for f in files], ignore_index=True)
真实案例:
某品牌有50家门店,每家门店每月发一个Excel文件,包含当月所有工单数据。运营专家需要汇总分析。
用Excel:打开50个文件,逐个复制粘贴,至少2小时。
用Pandas:上述代码,5分钟搞定。
第二部分:数据查看与选择
1. 查看数据基本信息
import pandas as pd
# 创建示例数据
df = pd.DataFrame({
'门店': ['北京朝阳店', '上海浦东店', '深圳南山店', '广州天河店', '成都高新店'],
'NPS': [85.6, 92.3, 78.9, 88.5, 91.2],
'营收': [1250000, 1580000, 980000, 1320000, 1450000],
'工单数': [800, 950, 620, 850, 920],
'技师数': [12, 15, 10, 13, 14]
})
# 查看前3行
print(df.head(3))
# 查看数据信息
print([df.info](http://df.info)())
# 输出:
# RangeIndex: 5 entries, 0 to 4
# Data columns (total 5 columns):
# 门店 5 non-null object
# NPS 5 non-null float64
# 营收 5 non-null int64
# ...
# 查看统计信息
print(df.describe())
# 输出:
# NPS 营收 工单数 技师数
# count 5.000000 5.000000e+00 5.000000 5.000000
# mean 87.300000 1.316000e+06 828.000000 12.800000
# std 5.482936 2.420744e+05 137.113092 1.923538
# ...
2. 选择列
# 选择一列
NPS列 = df['NPS']
print(NPS列)
# 选择多列
子集 = df[['门店', 'NPS', '营收']]
print(子集)
# 也可以用.运算符(列名不含空格时)
NPS列 = df.NPS
print(NPS列)
3. 选择行
# 用iloc按位置选择(从0开始)
第一行 = df.iloc[0] # 第1行
print(第一行)
前三行 = df.iloc[0:3] # 第1-3行
print(前三行)
# 用loc按索引选择
某行 = df.loc[2] # 索引为2的行
print(某行)
# 选择特定行和列
子集 = df.loc[0:2, ['门店', 'NPS']] # 前3行的门店和NPS列
print(子集)
4. 条件筛选(最重要!)
# 单条件筛选
高NPS门店 = df[df['NPS'] >= 90]
print(高NPS门店)
# 多条件筛选(且)
优秀门店 = df[(df['NPS'] >= 90) & (df['营收'] >= 1400000)]
print(优秀门店)
# 多条件筛选(或)
需关注门店 = df[(df['NPS'] < 80) | (df['营收'] < 1000000)]
print(需关注门店)
# 使用isin筛选
特定门店 = df[df['门店'].isin(['北京朝阳店', '上海浦东店'])]
print(特定门店)
实战案例:复杂筛选
# 筛选出:NPS在85-95之间,且营收超过120万的门店
目标门店 = df[
(df['NPS'] >= 85) &
(df['NPS'] <= 95) &
(df['营收'] > 1200000)
]
print(目标门店)
# 计算平均客单价,筛选出客单价超过1500的门店
df['客单价'] = df['营收'] / df['工单数']
高客单价门店 = df[df['客单价'] > 1500]
print(高客单价门店)
第三部分:数据清洗
1. 处理缺失值
import pandas as pd
import numpy as np
# 创建带缺失值的数据
df = pd.DataFrame({
'门店': ['北京朝阳店', '上海浦东店', '深圳南山店', '广州天河店'],
'NPS': [85.6, np.nan, 78.9, 88.5],
'营收': [1250000, 1580000, np.nan, 1320000],
'工单数': [800, 950, 620, np.nan]
})
# 查看缺失值
print(df.isnull()) # 返回布尔值
print(df.isnull().sum()) # 统计每列缺失值数量
# 删除含有缺失值的行
df_clean = df.dropna()
print(df_clean)
# 删除某列全为缺失值的列
df_clean = df.dropna(axis=1, how='all')
# 填充缺失值
df_filled = df.fillna(0) # 用0填充
df_filled = df.fillna(df.mean()) # 用平均值填充
df_filled = df.fillna(method='ffill') # 用前一个值填充
df_filled = df.fillna(method='bfill') # 用后一个值填充
# 为不同列填充不同值
df_filled = df.fillna({
'NPS': df['NPS'].mean(),
'营收': 0,
'工单数': df['工单数'].median()
})
2. 删除重复值
# 创建带重复值的数据
df = pd.DataFrame({
'客户ID': [1001, 1002, 1001, 1003, 1002],
'姓名': ['张三', '李四', '张三', '王五', '李四'],
'电话': ['138xxx', '139xxx', '138xxx', '137xxx', '139xxx']
})
# 查看重复值
print(df.duplicated()) # 返回布尔值
print(df.duplicated().sum()) # 统计重复行数
# 删除重复行
df_unique = df.drop_duplicates()
print(df_unique)
# 基于特定列判断重复
df_unique = df.drop_duplicates(subset=['客户ID'])
print(df_unique)
# 保留最后一次出现的记录
df_unique = df.drop_duplicates(subset=['客户ID'], keep='last')
3. 数据类型转换
# 查看数据类型
print(df.dtypes)
# 转换数据类型
df['NPS'] = df['NPS'].astype(float)
df['工单数'] = df['工单数'].astype(int)
df['门店'] = df['门店'].astype(str)
# 转换日期类型
df['日期'] = [pd.to](http://pd.to)_datetime(df['日期'])
# 处理错误的日期格式
df['日期'] = [pd.to](http://pd.to)_datetime(df['日期'], errors='coerce') # 无法转换的变成NaT
4. 字符串处理
# 创建示例数据
df = pd.DataFrame({
'客户姓名': [' 张三 ', 'LI SI', '王五'],
'电话': ['138-1234-5678', '13912345678', '139 1234 5678']
})
# 去除空格
df['客户姓名'] = df['客户姓名'].str.strip()
# 转换大小写
df['客户姓名'] = df['客户姓名'].str.upper() # 转大写
df['客户姓名'] = df['客户姓名'].str.lower() # 转小写
# 替换字符
df['电话'] = df['电话'].str.replace('-', '')
df['电话'] = df['电话'].str.replace(' ', '')
# 提取子串
df['区号'] = df['电话'].str[:3] # 前3位
# 判断是否包含
df['是否移动'] = df['电话'].str.startswith('13')
# 分割字符串
df[['姓', '名']] = df['客户姓名'].str.split(' ', expand=True)
第四部分:数据计算
1. 基础运算
# 创建示例数据
df = pd.DataFrame({
'门店': ['北京朝阳店', '上海浦东店', '深圳南山店'],
'营收': [1250000, 1580000, 980000],
'成本': [950000, 1200000, 780000],
'工单数': [800, 950, 620]
})
# 新增列:利润
df['利润'] = df['营收'] - df['成本']
# 新增列:利润率
df['利润率'] = df['利润'] / df['营收'] * 100
# 新增列:客单价
df['客单价'] = df['营收'] / df['工单数']
# 四舍五入
df['利润率'] = df['利润率'].round(2)
df['客单价'] = df['客单价'].round(0)
print(df)
2. 统计函数
# 求和
总营收 = df['营收'].sum()
print(f"总营收:{总营收:,}元")
# 平均值
平均营收 = df['营收'].mean()
print(f"平均营收:{平均营收:,.0f}元")
# 中位数
中位数营收 = df['营收'].median()
# 最大值、最小值
最高营收 = df['营收'].max()
最低营收 = df['营收'].min()
# 标准差
营收标准差 = df['营收'].std()
# 统计所有数值列
print(df.sum()) # 所有列求和
print(df.mean()) # 所有列平均值
print(df.describe()) # 完整统计信息
3. apply函数 — 自定义计算
# 定义评级函数
def 评估NPS(nps):
if nps >= 90:
return 'A级'
elif nps >= 85:
return 'B级'
elif nps >= 80:
return 'C级'
else:
return 'D级'
# 应用函数到整列
df['评级'] = df['NPS'].apply(评估NPS)
print(df[['门店', 'NPS', '评级']])
# 使用lambda表达式(匿名函数)
df['营收等级'] = df['营收'].apply(lambda x: '高' if x > 1300000 else '中' if x > 1100000 else '低')
# 对多列应用函数
def 计算综合得分(row):
# row是一行数据
nps_score = row['NPS'] / 100 * 0.6 # NPS占60%
revenue_score = min(row['营收'] / 2000000, 1) * 0.4 # 营收占40%
return (nps_score + revenue_score) * 100
df['综合得分'] = df.apply(计算综合得分, axis=1)
print(df[['门店', '综合得分']])
第五部分:分组聚合
1. groupby基础
# 创建示例数据
df = pd.DataFrame({
'战区': ['华北', '华北', '华东', '华东', '华南', '华南'],
'门店': ['北京朝阳店', '天津和平店', '上海浦东店', '杭州西湖店', '深圳南山店', '广州天河店'],
'NPS': [85.6, 82.3, 92.3, 89.5, 78.9, 88.5],
'营收': [1250000, 1100000, 1580000, 1350000, 980000, 1320000]
})
# 按战区分组,计算平均NPS
战区NPS = df.groupby('战区')['NPS'].mean()
print(战区NPS)
# 按战区分组,计算总营收
战区营收 = df.groupby('战区')['营收'].sum()
print(战区营收)
# 同时计算多个统计量
战区统计 = df.groupby('战区').agg({
'NPS': ['mean', 'min', 'max'],
'营收': ['sum', 'mean']
})
print(战区统计)
2. 实战案例:多维度分析
# 按战区和月份分组
df = pd.DataFrame({
'战区': ['华北', '华北', '华东', '华东'] * 3,
'月份': ['1月', '1月', '1月', '1月', '2月', '2月', '2月', '2月', '3月', '3月', '3月', '3月'],
'门店': ['北京店', '天津店', '上海店', '杭州店'] * 3,
'营收': [1250000, 1100000, 1580000, 1350000,
1300000, 1150000, 1620000, 1380000,
1280000, 1120000, 1600000, 1360000]
})
# 按战区和月份分组统计
分组统计 = df.groupby(['战区', '月份'])['营收'].sum()
print(分组统计)
# 重置索引,转为DataFrame
分组统计_df = df.groupby(['战区', '月份'])['营收'].sum().reset_index()
print(分组统计_df)
第六部分:数据透视表
# 创建数据透视表
pivot = df.pivot_table(
values='营收', # 要聚合的值
index='战区', # 行索引
columns='月份', # 列索引
aggfunc='sum' # 聚合函数
)
print(pivot)
# 输出示例:
# 1月 2月 3月
# 华北 2350000 2450000 2400000
# 华东 2930000 3000000 2960000
# 添加行列汇总
pivot_with_totals = df.pivot_table(
values='营收',
index='战区',
columns='月份',
aggfunc='sum',
margins=True, # 添加汇总行
margins_name='总计'
)
print(pivot_with_totals)
# 多个聚合函数
pivot_multi = df.pivot_table(
values='营收',
index='战区',
columns='月份',
aggfunc=['sum', 'mean', 'count']
)
print(pivot_multi)
学习小结
恭喜!你已经掌握了Pandas数据处理的核心功能:
✅ 数据读取:Excel、CSV、批量读取
✅ 数据查看:选择行列、条件筛选
✅ 数据清洗:缺失值、重复值、类型转换
✅ 数据计算:基础运算、统计函数、apply
✅ 分组聚合:groupby、数据透视表
这些技能,已经可以让你处理80%的日常数据工作。
下一步:Day 38-5 - Pandas实战案例(上)
在下一节中,我们将用一个完整的门店数据清洗案例,把所有知识串起来,让你真正理解如何在实际工作中应用Pandas。
准备好了吗?让我们继续! ?