第十二章

Pandas 库

Python数据分析的瑞士军刀

欢迎关注微信公众号

coder程 查令十街84号

目录

Pandas 简介

Pandas 是基于 NumPy 构建的数据分析库,提供了快速、灵活、明确的数据结构。

核心数据结构

结构 维度 描述 类比
Series 一维 带标签的数组(索引+值) Excel 的一列
DataFrame 二维 表格型数据结构(多列Series) Excel 整张表
Index 轴标签,不可变 行号/列名
安装与导入: pip install pandas ,然后 import pandas as pd

Series 对象的创建

import pandas as pd
import numpy as np

# 1. 从列表创建(默认整数索引)
s1 = pd.Series([1, 3, 5, 7, 9])
print(s1)
# 0    1
# 1    3
# ...

# 2. 指定索引
s2 = pd.Series([1, 3, 5], index=['a', 'b', 'c'])

# 3. 从字典创建
s3 = pd.Series({'a': 1, 'b': 2, 'c': 3})

# 4. 从NumPy数组创建
s4 = pd.Series(np.array([10, 20, 30]), index=['x', 'y', 'z'])

# 5. 标量广播
s5 = pd.Series(5, index=['a', 'b', 'c'])   # [5,5,5]

DataFrame 对象的创建

import pandas as pd

# 1. 从字典创建(值为列表)
df1 = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie'],
    'age': [25, 30, 35],
    'city': ['Beijing', 'Shanghai', 'Shenzhen']
})

# 2. 从字典创建(值为Series)
df2 = pd.DataFrame({
    'A': pd.Series([1, 2, 3]),
    'B': pd.Series([4, 5, 6])
})

# 3. 从二维数组创建
df3 = pd.DataFrame(np.arange(12).reshape(3, 4),
                   columns=['A', 'B', 'C', 'D'],
                   index=['x', 'y', 'z'])

# 4. 从文件读取
df_csv = pd.read_csv('data.csv')       # CSV文件
df_excel = pd.read_excel('data.xlsx')   # Excel文件
df_json = pd.read_json('data.json')     # JSON文件

DataFrame 对象性质

基本属性

import pandas as pd

df = pd.DataFrame({
    'A': [1,2,3],
    'B': [4,5,6],
    'C': [7,8,9]
}, index=['x','y','z'])

# 形状与维度
print(df.shape)       # (3, 3)
print(df.ndim)        # 2
print(df.size)        # 9
print(len(df))        # 3 - 行数

# 索引与列名
print(df.index)       # Index(['x','y','z'], dtype='object')
print(df.columns)     # Index(['A','B','C'], dtype='object')
print(df.dtypes)      # 每列数据类型
print(df.values)      # 底层NumPy数组

查看数据

# 查看开头/末尾
df.head(3)            # 前3行
df.tail(2)            # 后2行

# 统计摘要
df.describe()           # 数值列统计
df.info()               # 结构信息

# 转置
df.T                    # 行列互换

# 列访问
df['A']               # Series
df[['A', 'B']]        # DataFrame

# 行访问(loc/iloc)
df.loc['x']           # 按索引标签
df.iloc[0]            # 按整数位置

DataFrame 索引与切片

import pandas as pd

df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Charlie', 'David'],
    'age': [25, 30, 35, 28],
    'score': [85, 90, 78, 92]
}, index=['a', 'b', 'c', 'd'])

# loc - 基于标签的索引
df.loc['a']                      # 取'a'行
df.loc['a':'c']                  # 标签切片(含结束)
df.loc['a', 'name']              # 'a'行的'name'列
df.loc[:, ['name', 'age']]       # 多列

# iloc - 基于整数位置的索引
df.iloc[0]                       # 第0行
df.iloc[0:2]                     # 位置切片(不含结束)
df.iloc[0, 1]                     # 第0行第1列
df.iloc[:, 0:2]                   # 第0、1列

# 布尔索引(筛选)
df[df['age'] > 28]                # age > 28 的行
df[(df['age'] > 25) & (df['score'] >= 80)]

# 条件赋值
df.loc[df['age'] > 30, 'level'] = 'senior'
记忆口诀: loc = l abel(标签), iloc = i nteger(整数位置)。 loc 切片含结束, iloc 不含。

数值运算与统计分析

基础运算

import pandas as pd

df = pd.DataFrame({
    'A': [1, 2, 3, 4],
    'B': [10, 20, 30, 40]
})

# 算术运算(对齐索引)
df + 10               # 标量广播
df * 2                # 元素乘
df['A'] + df['B']     # Series相加
np.log(df)            # NumPy函数

# 统计函数
df.sum()              # 每列求和
df.mean()             # 均值
df.std()              # 标准差
df.min()              # 最小值
df.max()              # 最大值
df.cumsum()           # 累积和

高级统计

# 按轴统计
df.sum(axis=0)        # 列求和(默认)
df.sum(axis=1)        # 行求和

# 描述统计
df.describe()         # count/mean/std/min/25%/50%/75%/max
df['A'].value_counts() # 值频数统计
df.corr()             # 相关系数矩阵
df.cov()              # 协方差矩阵

# apply 自定义运算
df.apply(np.sum, axis=1)
df.apply(lambda x: x.max() - x.min())

# 滚动窗口
df.rolling(window=3).mean()   # 3窗口移动平均

处理缺失值

import pandas as pd
import numpy as np

df = pd.DataFrame({
    'A': [1, 2, np.nan, 4],
    'B': [5, np.nan, np.nan, 8],
    'C': [9, 10, 11, 12]
})

# 检测缺失值
df.isnull()           # 返回布尔DataFrame
df.isnull().sum()     # 每列缺失值个数
df.notnull()          # 非缺失值

# 删除缺失值
df.dropna()           # 删除含NaN的行
df.dropna(axis=1)     # 删除含NaN的列
df.dropna(how='all')  # 只删除全NaN的行
df.dropna(thresh=2)   # 保留至少有2个非NaN的行

# 填充缺失值
df.fillna(0)                    # 用0填充
df.fillna({'A': 0, 'B': 99})   # 按列指定填充值
df.fillna(method='ffill')       # 向前填充(用前一个值)
df.fillna(method='bfill')       # 向后填充(用后一个值)
df['A'].fillna(df['A'].mean())  # 用列均值填充

数据合并与连接

import pandas as pd

df1 = pd.DataFrame({'key': ['A','B','C'], 'val1': [1,2,3]})
df2 = pd.DataFrame({'key': ['B','C','D'], 'val2': [4,5,6]})

# 1. merge - 数据库风格的连接
pd.merge(df1, df2, on='key')               # 内连接(默认)
pd.merge(df1, df2, on='key', how='left')  # 左连接
pd.merge(df1, df2, on='key', how='right') # 右连接
pd.merge(df1, df2, on='key', how='outer') # 外连接

# 2. concat - 轴向连接
pd.concat([df1, df2], axis=0)   # 纵向拼接(堆叠)
pd.concat([df1, df2], axis=1)   # 横向拼接(并排放)

# 3. join - 按索引合并
df1.set_index('key', inplace=True)
df2.set_index('key', inplace=True)
df1.join(df2, how='outer')

# 4. append(已弃用,用concat替代)
pd.concat([df1, df2])   # df1.append(df2) 的替代方案
连接方式 说明
inner 只保留两表都有的键(交集)
outer 保留所有键(并集)
left 保留左表所有键,右表无匹配填NaN
right 保留右表所有键,左表无匹配填NaN

分组与聚合

import pandas as pd

df = pd.DataFrame({
    'team': ['A', 'B', 'A', 'B', 'A', 'B'],
    'year': [2020, 2020, 2021, 2021, 2021, 2022],
    'sales': [100, 150, 200, 120, 180, 90],
    'profit': [20, 30, 50, 25, 40, 15]
})

# 单列分组
df.groupby('team')['sales'].sum()       # 各团队总销售额
df.groupby('team').mean()              # 各团队均值

# 多列分组
df.groupby(['team', 'year']).sum()      # 按团队和年份分组

# 多指标聚合
df.groupby('team').agg({
    'sales': ['sum', 'mean', 'max'],
    'profit': ['sum', 'mean']
})

# apply + 自定义函数
df.groupby('team').apply(lambda x: x['sales'].max() - x['sales'].min())

# transform - 保持原形状
df['sales_rank'] = df.groupby('team')['sales'].transform('rank')

透视表与其他操作

透视表 pivot_table

import pandas as pd

# 创建透视表
pd.pivot_table(
    df,
    values='sales',          # 聚合的值
    index='team',            # 行索引
    columns='year',          # 列索引
    aggfunc='sum',           # 聚合函数
    fill_value=0             # 缺失值填充
)

# 多值多函数
pd.pivot_table(
    df,
    values=['sales', 'profit'],
    index='team',
    aggfunc={'sales': 'sum', 'profit': 'mean'}
)

# margins 添加总计
pd.pivot_table(df, values='sales',
    index='team', columns='year',
    aggfunc='sum', margins=True)

其他常用操作

# 去重
df.drop_duplicates()
df.drop_duplicates(subset=['team'])

# 排序
df.sort_values('sales', ascending=False)
df.sort_values(['team', 'sales'])

# 字符串操作
df['name'].str.upper()
df['name'].str.contains('A')
df['name'].str.split(' ').str[0]

# 日期处理
df['date'] = pd.to_datetime(df['date'])
df['date'].dt.year

# 离散化(分箱)
pd.cut(df['sales'], bins=3, labels=['低','中','高'])

本章总结

Pandas 是数据清洗、预处理、探索性分析的首选工具,掌握它等于掌握了数据分析的半壁江山。

下一章 ▶