当前位置:首页 > 学习笔记 > 正文内容

Pandas 数据分析完全指南:从入门到精通

Pandas 是 Python 数据科学生态中最核心的数据分析库,提供了 DataFrame 和 Series 两大核心数据结构,支持从数据读取、清洗、转换、聚合到可视化分析的全流程操作。本文系统讲解 Pandas 核心操作,助你从入门到精通数据分析。

Pandas 数据分析完全指南

## 一、Pandas 简介与环境准备 Pandas 名字来源于 "Panel Data"(面板数据),由 Wes McKinney 于 2008 年开发,现已成为 Python 数据分析领域的标准工具。它建立在 NumPy 之上,提供了高效的数据操作能力,特别适合处理表格型或异质型数据。 安装 Pandas:
pip install pandas numpy
导入常用约定:
import pandas as pd
import numpy as np
Pandas 的两大核心数据结构是 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 转载需授权!

分享到:

版权声明:本文由廖万里的博客发布,如需转载请注明出处。


发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。