Pandas 数据分析完全指南:从入门到精通
Pandas 是 Python 数据科学生态中最核心的数据分析库,提供了 DataFrame 和 Series 两大核心数据结构,支持从数据读取、清洗、转换、聚合到可视化分析的全流程操作。本文系统讲解 Pandas 核心操作,助你从入门到精通数据分析。
pip install pandas numpy导入常用约定:
import pandas as pd import numpy as npPandas 的两大核心数据结构是 Series(一维序列)和 DataFrame(二维表格)。Series 类似带标签的一维数组,DataFrame 则像 Excel 表格或 SQL 表,由多个 Series 组成。 ## 二、DataFrame 核心操作 ### 2.1 创建 DataFrame DataFrame 可以从字典、列表、NumPy 数组等多种方式创建:
# 从字典创建
data = {
'name': ['张三', '李四', '王五', '赵六'],
'age': [25, 30, 35, 28],
'city': ['北京', '上海', '广州', '深圳'],
'salary': [15000, 20000, 18000, 16000]
}
df = pd.DataFrame(data)
# 从列表创建
df2 = pd.DataFrame(
[[1, 'A'], [2, 'B'], [3, 'C']],
columns=['id', 'value']
)
# 从 NumPy 数组创建
arr = np.random.randn(5, 3)
df3 = pd.DataFrame(arr, columns=['A', 'B', 'C'])
### 2.2 数据查看与基本信息
# 查看前几行(默认 5 行)
df.head()
# 查看后几行
df.tail(3)
# 数据形状
print(f"行数: {df.shape[0]}, 列数: {df.shape[1]}")
# 数据类型
df.dtypes
# 统计摘要
df.describe()
# 查看索引和列名
df.index
df.columns
# 内存使用情况
df.memory_usage()
### 2.3 数据选择与过滤
# 选择单列(返回 Series) df['name'] df.name # 属性访问方式 # 选择多列(返回 DataFrame) df[['name', 'age', 'salary']] # 按标签选择 .loc df.loc[0] # 第一行 df.loc[0:2, 'name'] # 前三行的 name 列 df.loc[df['age'] > 28, ['name', 'salary']] # 条件筛选 # 按位置选择 .iloc df.iloc[0] # 第一行 df.iloc[0:3, 0:2] # 前三行的前两列 df.iloc[[0, 2], [1, 3]] # 指定行列 # 条件过滤 df[df['age'] > 28] df[(df['age'] >= 25) & (df['salary'] > 15000)] # 使用 isin df[df['city'].isin(['北京', '上海'])]## 三、数据清洗 ### 3.1 缺失值处理
# 创建含缺失值的示例数据
df_missing = pd.DataFrame({
'A': [1, 2, np.nan, 4],
'B': [np.nan, 2, 3, 4],
'C': [1, np.nan, np.nan, 4]
})
# 检测缺失值
df_missing.isnull()
df_missing.isnull().sum() # 每列缺失数量
# 删除缺失值
df_missing.dropna() # 删除含缺失值的行
df_missing.dropna(axis=1) # 删除含缺失值的列
df_missing.dropna(how='all') # 全部缺失才删除
df_missing.dropna(subset=['A', 'B']) # 指定列判断
# 填充缺失值
df_missing.fillna(0) # 用固定值填充
df_missing.fillna(method='ffill') # 前向填充
df_missing.fillna(method='bfill') # 后向填充
df_missing.fillna(df_missing.mean()) # 用均值填充
### 3.2 重复值处理
# 检测重复值 df.duplicated() df.duplicated(subset=['name']) # 指定列判断 # 删除重复值 df.drop_duplicates() df.drop_duplicates(subset=['name'], keep='first') # 保留第一个 df.drop_duplicates(subset=['name'], keep='last') # 保留最后一个### 3.3 数据类型转换
# 查看数据类型 df.dtypes # 转换数据类型 df['age'] = df['age'].astype(float) df['salary'] = df['salary'].astype(str) # 智能类型推断 df.convert_dtypes() # 数值转换(处理非数值) pd.to_numeric(df['column'], errors='coerce') # 无效值转 NaN # 日期时间转换 df['date'] = pd.to_datetime(df['date'])## 四、数据转换 ### 4.1 数据排序
# 按索引排序
df.sort_index()
df.sort_index(ascending=False) # 降序
# 按值排序
df.sort_values('age')
df.sort_values(['age', 'salary'], ascending=[True, False])
### 4.2 数据映射与函数应用
# map:Series 元素级映射
df['age_group'] = df['age'].map(lambda x: '青年' if x < 30 else '中年')
# apply:对 Series 或 DataFrame 应用函数
df['salary_k'] = df['salary'].apply(lambda x: x / 1000)
df.apply(lambda row: row['age'] * 100, axis=1)
# applymap:DataFrame 元素级操作
df[['age', 'salary']].applymap(lambda x: f'{x:.2f}')
# replace:值替换
df['city'].replace({'北京': 'Beijing', '上海': 'Shanghai'})
# 分箱操作
df['age_bin'] = pd.cut(df['age'], bins=[0, 25, 30, 40], labels=['青年', '壮年', '中年'])
df['salary_quartile'] = pd.qcut(df['salary'], q=4, labels=['Q1', 'Q2', 'Q3', 'Q4'])
### 4.3 字符串操作
# Pandas 字符串方法(通过 .str 访问器)
df['name'].str.upper() # 转大写
df['name'].str.lower() # 转小写
df['name'].str.len() # 字符串长度
df['name'].str.contains('张') # 是否包含
df['name'].str.startswith('张') # 开头判断
df['name'].str.replace('张', 'Mr.') # 替换
df['name'].str.split('') # 分割
# 正则表达式
df['text'].str.extract(r'(\d+)') # 提取数字
df['text'].str.findall(r'\d+') # 查找所有匹配
## 五、分组与聚合
### 5.1 基础分组操作
# 创建示例数据
df_sales = pd.DataFrame({
'category': ['A', 'B', 'A', 'B', 'A', 'C', 'B', 'C'],
'product': ['P1', 'P2', 'P3', 'P4', 'P5', 'P6', 'P7', 'P8'],
'sales': [100, 200, 150, 300, 120, 250, 180, 220],
'region': ['北', '南', '北', '南', '北', '东', '南', '东']
})
# 单列分组
grouped = df_sales.groupby('category')
# 多列分组
grouped_multi = df_sales.groupby(['category', 'region'])
# 查看分组
grouped.groups
grouped.size() # 每组大小
### 5.2 聚合操作
# 常用聚合函数
grouped['sales'].sum()
grouped['sales'].mean()
grouped['sales'].max()
grouped['sales'].min()
grouped['sales'].count()
grouped['sales'].std()
# 多个聚合函数
grouped['sales'].agg(['sum', 'mean', 'count'])
# 不同列应用不同聚合
grouped.agg({
'sales': ['sum', 'mean'],
'product': 'count'
})
# 自定义聚合函数
grouped['sales'].agg(lambda x: x.max() - x.min())
### 5.3 transform 与 apply
# transform:返回与原数据相同形状
df_sales['sales_mean'] = df_sales.groupby('category')['sales'].transform('mean')
# 计算每行占组内总量的比例
df_sales['sales_ratio'] = df_sales.groupby('category')['sales'].transform(
lambda x: x / x.sum()
)
# apply:对每组应用函数
def top_n(group, n=2):
return group.nlargest(n, 'sales')
df_sales.groupby('category').apply(top_n)
## 六、合并与连接
### 6.1 concat 拼接
# 创建示例数据
df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
df2 = pd.DataFrame({'A': [5, 6], 'B': [7, 8]})
# 纵向拼接
pd.concat([df1, df2])
pd.concat([df1, df2], ignore_index=True) # 重置索引
# 横向拼接
pd.concat([df1, df2], axis=1)
# 处理列不一致情况
df3 = pd.DataFrame({'A': [9, 10], 'C': [11, 12]})
pd.concat([df1, df3], join='inner') # 只保留共有列
### 6.2 merge 连接
# 创建示例数据
left = pd.DataFrame({
'key': ['A', 'B', 'C', 'D'],
'value_left': [1, 2, 3, 4]
})
right = pd.DataFrame({
'key': ['A', 'B', 'E', 'F'],
'value_right': [5, 6, 7, 8]
})
# 内连接(默认)
pd.merge(left, right, on='key')
# 左连接
pd.merge(left, right, on='key', how='left')
# 右连接
pd.merge(left, right, on='key', how='right')
# 外连接
pd.merge(left, right, on='key', how='outer')
# 多键连接
pd.merge(left, right, on=['key1', 'key2'])
# 不同列名连接
pd.merge(left, right, left_on='key_left', right_on='key_right')
### 6.3 join 连接
# join 基于索引连接
df_left = pd.DataFrame({'A': [1, 2]}, index=['a', 'b'])
df_right = pd.DataFrame({'B': [3, 4]}, index=['a', 'b'])
df_left.join(df_right)
# 多个 DataFrame 连接
df_left.join([df_right, df_another])
## 七、时间序列处理
### 7.1 时间序列创建
# 创建日期范围
dates = pd.date_range('2024-01-01', periods=10, freq='D')
# 创建时间序列数据
ts = pd.Series(np.random.randn(10), index=dates)
# 常用频率
pd.date_range('2024-01-01', periods=12, freq='M') # 月末
pd.date_range('2024-01-01', periods=4, freq='Q') # 季度末
pd.date_range('2024-01-01', periods=10, freq='W') # 周
# 转换为时间序列
df['date'] = pd.to_datetime(df['date'])
df.set_index('date', inplace=True)
### 7.2 时间序列索引与切片
# 创建时间序列
ts = pd.Series(
np.random.randn(365),
index=pd.date_range('2024-01-01', periods=365, freq='D')
)
# 切片访问
ts['2024-01-01':'2024-01-10'] # 日期范围
ts['2024-01'] # 整月数据
ts['2024'] # 整年数据
# 提取时间属性
ts.index.year
ts.index.month
ts.index.day
ts.index.dayofweek
ts.index.quarter
### 7.3 重采样与滚动窗口
# 重采样(降采样)
ts.resample('W').mean() # 周均值
ts.resample('M').sum() # 月总和
ts.resample('Q').agg(['mean', 'sum', 'count'])
# 升采样
ts.resample('H').asfreq() # 小时频率,填充 NaN
ts.resample('H').ffill() # 前向填充
# 滚动窗口
ts.rolling(window=7).mean() # 7日移动平均
ts.rolling(window=30).std() # 30日滚动标准差
# 指数加权移动平均
ts.ewm(span=10).mean()
# 窗口操作
ts.rolling(window=7, center=True).mean() # 居中窗口
### 7.4 时区处理
# 设置时区
ts_utc = ts.tz_localize('UTC')
# 转换时区
ts_shanghai = ts_utc.tz_convert('Asia/Shanghai')
# 时区感知时间范围
pd.date_range('2024-01-01', periods=5, freq='D', tz='Asia/Shanghai')
## 八、数据可视化
Pandas 集成了 Matplotlib,提供便捷的绑定方法。配合 Matplotlib 和 Seaborn 可实现更丰富的可视化。
### 8.1 基础绑定
import matplotlib.pyplot as plt
# 设置中文显示
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
# 创建示例数据
df_plot = pd.DataFrame({
'A': np.random.randn(100).cumsum(),
'B': np.random.randn(100).cumsum(),
'C': np.random.randn(100).cumsum()
})
# 折线图
df_plot.plot()
df_plot.plot(figsize=(12, 6), title='趋势图')
# 柱状图
df_plot.plot(kind='bar')
df_plot.plot(kind='barh') # 水平柱状图
# 散点图
df.plot.scatter(x='age', y='salary', c='red')
# 直方图
df['salary'].plot.hist(bins=20)
# 箱线图
df.plot.box()
# 饼图
df['city'].value_counts().plot.pie(autopct='%1.1f%%')
# 面积图
df_plot.plot.area(alpha=0.5)
### 8.2 高级可视化
import seaborn as sns
# 设置样式
sns.set_style('whitegrid')
# 热力图
corr = df.corr()
sns.heatmap(corr, annot=True, cmap='coolwarm')
# 分布图
sns.histplot(df['salary'], kde=True)
# 箱线图
sns.boxplot(x='category', y='sales', data=df_sales)
# 小提琴图
sns.violinplot(x='category', y='sales', data=df_sales)
# 配对图
sns.pairplot(df)
## 九、实战案例:电商销售分析
下面通过一个电商销售数据集,演示 Pandas 数据分析完整流程。
### 9.1 数据准备
# 创建模拟电商数据
np.random.seed(42)
n = 1000
df_ecom = pd.DataFrame({
'order_id': range(1, n + 1),
'customer_id': np.random.randint(1, 101, n),
'product_category': np.random.choice(['电子产品', '服装', '食品', '家居', '美妆'], n),
'amount': np.random.uniform(50, 2000, n).round(2),
'quantity': np.random.randint(1, 6, n),
'order_date': pd.date_range('2024-01-01', periods=n, freq='H'),
'region': np.random.choice(['华北', '华东', '华南', '西部'], n),
'payment_method': np.random.choice(['支付宝', '微信', '信用卡', '银行卡'], n)
})
# 计算总金额
df_ecom['total'] = df_ecom['amount'] * df_ecom['quantity']
print(df_ecom.head())
print(df_ecom.info())
### 9.2 数据探索与清洗
# 基础统计
print(df_ecom.describe())
# 检查缺失值
print(df_ecom.isnull().sum())
# 检查重复订单
print(f"重复订单数: {df_ecom['order_id'].duplicated().sum()}")
# 查看各类别分布
print(df_ecom['product_category'].value_counts())
### 9.3 多维度分析
# 设置时间索引
df_ecom.set_index('order_date', inplace=True)
# 按小时的订单量趋势
hourly_orders = df_ecom.resample('H')['order_id'].count()
# 按产品类别统计
category_stats = df_ecom.groupby('product_category').agg({
'total': ['sum', 'mean', 'count'],
'quantity': 'sum'
}).round(2)
print(category_stats)
# 各地区销售排名
region_sales = df_ecom.groupby('region')['total'].sum().sort_values(ascending=False)
print(region_sales)
# 支付方式占比
payment_dist = df_ecom['payment_method'].value_counts(normalize=True)
print(payment_dist)
# 客户价值分析(RFM 模型简化版)
customer_value = df_ecom.groupby('customer_id').agg({
'total': 'sum',
'order_id': 'count',
'order_date': 'max'
}).rename(columns={'order_id': 'order_count'})
print(customer_value.head(10))
### 9.4 可视化呈现
# 设置画布
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
# 各类别销售额
category_sales = df_ecom.groupby('product_category')['total'].sum().sort_values()
axes[0, 0].barh(category_sales.index, category_sales.values, color='steelblue')
axes[0, 0].set_title('各品类销售额')
axes[0, 0].set_xlabel('销售额')
# 地区销售分布
region_sales.plot.pie(ax=axes[0, 1], autopct='%1.1f%%', colors=sns.color_palette('pastel'))
axes[0, 1].set_title('地区销售占比')
axes[0, 1].set_ylabel('')
# 订单金额分布
axes[1, 0].hist(df_ecom['total'], bins=30, color='coral', edgecolor='white')
axes[1, 0].set_title('订单金额分布')
axes[1, 0].set_xlabel('订单金额')
axes[1, 0].set_ylabel('频数')
# 支付方式占比
payment_dist.plot(kind='bar', ax=axes[1, 1], color='teal')
axes[1, 1].set_title('支付方式分布')
axes[1, 1].set_xlabel('支付方式')
axes[1, 1].set_ylabel('占比')
axes[1, 1].tick_params(axis='x', rotation=45)
plt.tight_layout()
plt.savefig('ecom_analysis.png', dpi=150)
plt.show()
### 9.5 分析结论
通过数据分析,我们得出以下洞察:
1. **品类表现**:电子产品销售额最高,美妆客单价增长潜力大
2. **地区分布**:华东地区贡献最大,西部地区有拓展空间
3. **支付偏好**:支付宝和微信占据主导地位
4. **客户价值**:前 20% 客户贡献了约 60% 的销售额
## 总结
Pandas 作为 Python 数据分析的核心库,提供了从数据读取、清洗、转换、分析到可视化的完整工具链。掌握 DataFrame 操作、分组聚合、合并连接、时间序列处理等核心技能,是成为数据分析师的必备基础。
关键要点回顾:
1. **DataFrame 操作**:熟练使用 loc/iloc 进行数据选择,理解索引机制
2. **数据清洗**:缺失值和重复值处理是数据准备的关键步骤
3. **分组聚合**:groupby + agg 是数据分析的核心模式
4. **合并连接**:concat/merge/join 实现数据的横向和纵向整合
5. **时间序列**:resample 和 rolling 是处理时序数据的利器
6. **可视化**:绑定绑定方法快速出图,Seaborn 提升美观度
持续实践是精通 Pandas 的最佳路径。建议从真实业务场景出发,逐步积累数据处理经验,形成自己的分析套路和代码模板。本文链接:https://www.kkkliao.cn/?id=960 转载需授权!
版权声明:本文由廖万里的博客发布,如需转载请注明出处。



手机流量卡
免费领卡
号卡合伙人
产品服务
关于本站
