Pandas 高级功能
Pandas 提供了非常强大的数据操作功能,适用于复杂的数据清洗、分析、聚合和时间序列处理等任务。掌握 Pandas 的高级功能,可以大大提高数据处理和分析的效率。
一、数据合并与连接
Pandas 提供了多个方法来合并和连接不同的 DataFrame,例如 merge()
、concat()
和 join()
。这些方法常用于处理多个数据集和复杂的合并任务。
1. merge()
— 数据库风格的连接
merge()
方法允许根据某些列对两个 DataFrame 进行合并,类似 SQL 中的 JOIN
操作。支持内连接、外连接、左连接和右连接。
参数 | 说明 |
---|---|
left |
左侧 DataFrame |
right |
右侧 DataFrame |
how |
合并方式,支持 'inner' , 'outer' , 'left' , 'right' |
on |
连接的列名(如果两侧列名不同,可使用 left_on 和 right_on ) |
left_on |
左侧 DataFrame 的连接列 |
right_on |
右侧 DataFrame 的连接列 |
suffixes |
添加后缀,以区分重复的列名 |
实例
# 示例数据
left = pd.DataFrame({'ID': [1, 2, 3], 'Name': ['Alice', 'Bob', 'Charlie']})
right = pd.DataFrame({'ID': [1, 2, 4], 'Age': [24, 27, 22]})
# 使用 merge 进行内连接
result = pd.merge(left, right, on='ID', how='inner')
print(result)
输出:
ID Name Age 0 1 Alice 24 1 2 Bob 27
2. concat()
— 沿轴连接
concat()
用于将多个 DataFrame 沿指定轴(行或列)进行连接,常用于行合并(垂直连接)或列合并(水平连接)。
参数 | 说明 |
---|---|
objs |
需要合并的 DataFrame 列表 |
axis |
合并的轴,0 表示按行合并,1 表示按列合并 |
ignore_index |
是否忽略索引,重新生成索引(默认为 False ) |
keys |
为合并的对象提供层次化索引 |
实例
# 示例数据
df1 = pd.DataFrame({'A': [1, 2, 3]})
df2 = pd.DataFrame({'A': [4, 5, 6]})
# 行合并
result = pd.concat([df1, df2], axis=0, ignore_index=True)
print(result)
输出:
A 0 1 1 2 2 3 3 4 4 5 5 6
3. join()
— 基于索引连接
join()
方法是 Pandas 中的简化连接操作,通常用于基于索引将多个 DataFrame 连接。
参数 | 说明 |
---|---|
other |
需要连接的另一个 DataFrame |
how |
合并方式,支持 'left' , 'right' , 'outer' , 'inner' |
on |
使用的连接列,默认基于索引 |
实例
# 示例数据
left = pd.DataFrame({'A': [1, 2, 3]}, index=[1, 2, 3])
right = pd.DataFrame({'B': [4, 5, 6]}, index=[1, 2, 4])
# 使用 join 进行连接
result = left.join(right, how='inner')
print(result)
输出:
A B 1 1 4 2 2 5
二、透视表与交叉表
Pandas 提供了 pivot_table()
方法来创建透视表,和 crosstab()
方法来计算交叉表。透视表和交叉表都非常适合数据的汇总和重新排列。
1. pivot_table()
— 创建透视表
参数 | 说明 |
---|---|
data |
输入的数据 |
values |
要汇总的列 |
index |
用作行索引的列 |
columns |
用作列索引的列 |
aggfunc |
聚合函数,默认为 mean ,可以是 sum , count 等 |
fill_value |
填充缺失值 |
实例
# 示例数据
data = {'Date': ['2024-01-01', '2024-01-02', '2024-01-03', '2024-01-04'],
'Category': ['A', 'B', 'A', 'B'],
'Sales': [100, 150, 200, 250]}
df = pd.DataFrame(data)
# 创建透视表
pivot_table = pd.pivot_table(df, values='Sales', index='Date', columns='Category', aggfunc='sum', fill_value=0)
print(pivot_table)
输出:
Category A B Date 2024-01-01 100 0 2024-01-02 0 150 2024-01-03 200 0 2024-01-04 0 250
2. crosstab()
— 创建交叉表
参数 | 说明 |
---|---|
index |
行标签 |
columns |
列标签 |
values |
用于计算的数据(可选) |
aggfunc |
聚合函数,默认 count |
实例
# 示例数据
data = {'Category': ['A', 'B', 'A', 'B', 'A', 'B'],
'Region': ['North', 'South', 'North', 'South', 'West', 'East']}
df = pd.DataFrame(data)
# 创建交叉表
cross_table = pd.crosstab(df['Category'], df['Region'])
print(cross_table)
输出:
Region East North South West Category A 0 2 0 1 B 1 0 1 0
三、自定义函数应用
Pandas 提供了多种方法应用自定义函数,用于数据清洗和转换。
1. apply()
— 应用函数到 DataFrame 或 Series 上
apply()
方法允许在 DataFrame 或 Series 上应用自定义函数,支持对行或列进行操作。
参数 | 说明 |
---|---|
func |
需要应用的函数 |
axis |
默认为 0 ,表示按列应用;1 表示按行应用 |
raw |
是否传递原始数据(默认为 False ) |
result_type |
定义输出的类型,如 expand , reduce , broadcast |
实例
# 示例数据
df = pd.DataFrame({'A': [1, 2, 3, 4], 'B': [10, 20, 30, 40]})
# 定义自定义函数
def custom_func(x):
return x * 2
# 在列上应用函数
df['A'] = df['A'].apply(custom_func)
print(df)
输出:
A B 0 2 10 1 4 20 2 6 30 3 8 40
2. applymap()
— 在整个 DataFrame 上应用函数
applymap()
只能应用于 DataFrame,作用于 DataFrame 中的每个元素。
参数 | 说明 |
---|---|
func |
需要应用的函数 |
实例
# 示例数据
df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
# 在 DataFrame 上应用自定义函数
df = df.applymap(lambda x: x ** 2)
print(df)
输出:
A B 0 1 16 1 4 25 2 9 36
3. map()
— 应用函数到 Series 上
map()
可以对 Series 中的每个元素应用一个函数或一个映射关系。
参数 | 说明 |
---|---|
arg |
应用的函数,字典或 Series |
实例
# 示例数据
df = pd.DataFrame({'A': ['cat', 'dog', 'rabbit']})
# 使用字典进行映射
df['A'] = df['A'].map({'cat': 'kitten', 'dog': 'puppy'})
print(df)
输出:
A 0 kitten 1 puppy 2 NaN
四、分组操作与聚合
Pandas 中的 groupby()
方法非常强大,可以用于分组聚合、转换数据和过滤数据。通过 groupby()
,可以将数据根据某些条件分组,进行聚合运算,如求和、均值、计数等。
1. groupby()
— 数据分组
参数 | 说明 |
---|---|
by |
按照哪个列或索引分组 |
axis |
分组的轴,默认为 0 ,即按行进行分组 |
level |
按照索引的级别进行分组(适用于 MultiIndex) |
实例
# 示例数据
df = pd.DataFrame({
'Category': ['A', 'B', 'A', 'B', 'A', 'B'],
'Value': [10, 20, 30, 40, 50, 60]
})
# 按照 Category 列进行分组并计算每组的总和
grouped = df.groupby('Category')['Value'].sum()
print(grouped)
输出:
Category A 90 B 120 Name: Value, dtype: int64
2. 聚合操作(agg()
)
agg()
用于执行复杂的聚合操作,可以传入多个函数来同时计算多个聚合值。
参数 | 说明 |
---|---|
func |
聚合函数,可以是字符串或自定义函数 |
实例
# 示例数据
df = pd.DataFrame({
'Category': ['A', 'B', 'A', 'B', 'A', 'B'],
'Value': [10, 20, 30, 40, 50, 60]
})
# 使用 agg() 来进行多个聚合操作
grouped = df.groupby('Category')['Value'].agg([sum, min, max])
print(grouped)
输出:
sum min max Category A 90 10 50 B 120 20 60
五、时间序列处理
Pandas 提供了强大的时间序列处理功能,包括日期解析、频率转换、日期范围生成、时间窗口操作等。
1. date_range()
— 生成时间序列
参数 | 说明 |
---|---|
start |
起始日期 |
end |
结束日期 |
periods |
生成的时间点数 |
freq |
频率(如 D 表示天,H 表示小时等) |
实例
# 生成时间序列
date_range = pd.date_range(start='2024-01-01', periods=5, freq='D')
print(date_range)
输出:
DatetimeIndex(['2024-01-01', '2024-01-02', '2024-01-03', '2024-01-04', '2024-01-05'], dtype='datetime64[ns]', freq='D')
2. 日期和时间的偏移
使用 pd.Timedelta()
可以进行时间的加减操作。
实例
# 日期偏移
date = pd.to_datetime('2024-01-01')
new_date = date + pd.Timedelta(days=10)
print(new_date)
输出:
2024-01-11 00:00:00
3. 时间窗口操作(Rolling, Expanding)
使用 rolling()
和 expanding()
方法进行滚动和扩展窗口操作,常用于时间序列中的移动平均等计算。
方法 | 说明 |
---|---|
rolling() |
计算滚动窗口操作,常用于移动平均等 |
expanding() |
计算扩展窗口操作,累计值 |
实例
# 示例数据
df = pd.DataFrame({'Value': [10, 20, 30, 40, 50]})
# 计算 3 天滚动平均
df['Rolling_Mean'] = df['Value'].rolling(window=3).mean()
print(df)
输出:
Value Rolling_Mean 0 10 NaN 1 20 NaN 2 30 20.000000 3 40 30.000000 4 50 40.000000
六、缺失值处理
Pandas 提供了多种方法来处理缺失值(如 NaN)。常见的操作包括填充缺失值、删除缺失值等。
方法 | 说明 |
---|---|
isna() |
检查缺失值,返回布尔值 |
fillna() |
填充缺失值 |
dropna() |
删除包含缺失值的行或列 |
实例
import numpy as np
# 示例数据
df = pd.DataFrame({
'A': [1, 2, np.nan, 4],
'B': [5, np.nan, 7, 8]
})
# 填充缺失值
df_filled = df.fillna(0)
print(df_filled)
输出:
A B 0 1 5 1 2 0 2 0 7 3 4 8
七、多重索引(MultiIndex)
Pandas 提供了多重索引(MultiIndex)的功能,使得可以在 DataFrame 或 Series 中处理复杂的数据结构,尤其适用于层次化的数据。通过多重索引,我们能够对数据进行分组、选择、切片以及聚合等操作。
1. 创建多重索引
可以通过 pd.MultiIndex.from_tuples()
、pd.MultiIndex.from_product()
或者 set_index()
方法来创建多重索引。
方法 1: pd.MultiIndex.from_tuples()
使用元组来创建多重索引,每个元组对应一个索引层级。
参数 | 说明 |
---|---|
tuples |
每个元组对应一个索引值 |
names |
每个索引级别的名称(可选) |
实例
# 创建元组
index_tuples = [('A', 1), ('A', 2), ('B', 1), ('B', 2)]
# 创建多重索引
multi_index = pd.MultiIndex.from_tuples(index_tuples, names=['Letter', 'Number'])
# 创建 DataFrame
df = pd.DataFrame({'Value': [10, 20, 30, 40]}, index=multi_index)
print(df)
输出:
Value Letter Number A 1 10 2 20 B 1 30 2 40
方法 2: pd.MultiIndex.from_product()
使用多个列表的笛卡尔积来创建多重索引,适合用于数据维度较多的情况。
参数 | 说明 |
---|---|
iterables |
多个列表或数组 |
names |
每个索引级别的名称(可选) |
实例
# 创建多个列表
index_values = [['A', 'B'], [1, 2]]
# 创建多重索引
multi_index = pd.MultiIndex.from_product(index_values, names=['Letter', 'Number'])
# 创建 DataFrame
df = pd.DataFrame({'Value': [10, 20, 30, 40]}, index=multi_index)
print(df)
输出:
Value Letter Number A 1 10 2 20 B 1 30 2 40
方法 3: 使用 set_index()
创建多重索引
set_index()
方法可以将 DataFrame 的列转换为多重索引,适用于从已有的数据创建多重索引。
参数 | 说明 |
---|---|
keys |
用作索引的列名(可以是单列或多列) |
实例
# 示例数据
data = {
'Letter': ['A', 'A', 'B', 'B'],
'Number': [1, 2, 1, 2],
'Value': [10, 20, 30, 40]
}
df = pd.DataFrame(data)
# 设置多重索引
df.set_index(['Letter', 'Number'], inplace=True)
print(df)
输出:
Value Letter Number A 1 10 2 20 B 1 30 2 40
2. 多重索引的操作
1. 访问多重索引数据
可以通过层级索引来访问数据。通过 loc[]
或 xs()
(cross-section)可以方便地进行数据选择。
使用 loc[]
选择数据:
实例
# 示例数据
data = {
'Letter': ['A', 'A', 'B', 'B'],
'Number': [1, 2, 1, 2],
'Value': [10, 20, 30, 40]
}
df = pd.DataFrame(data)
# 设置多重索引
df.set_index(['Letter', 'Number'], inplace=True)
# 选择 'A' 类别,所有 'Number' 为 1 的数据
print(df.loc['A', 1])
输出:
Value 10 Name: (A, 1), dtype: int64
使用 xs()
获取交叉数据:
xs()
方法可以在多重索引中选择指定级别的切片。
实例
print(df.xs(1, level='Number'))
输出:
Value Letter A 10 B 30
2. 多重索引的切片
Pandas 支持对多重索引进行切片操作,允许通过索引级别选择不同的子集。
实例
print(df.loc['A'])
输出:
Value Number 1 10 2 20
3. 排序多重索引
Pandas 的 sort_index()
方法支持对多重索引进行排序。
实例
df_sorted = df.sort_index(level=['Letter', 'Number'], ascending=[True, False])
print(df_sorted)
输出:
Value Letter Number A 2 20 1 10 B 2 40 1 30
4. 聚合操作
多重索引结合 groupby()
可以进行强大的聚合操作,适用于复杂数据的统计分析。
实例
df_grouped = df.groupby(['Letter', 'Number']).sum()
print(df_grouped)
输出:
Value Letter Number A 1 10 2 20 B 1 30 2 40
5. 重设索引
可以使用 reset_index()
方法将多重索引重置为普通的列。
实例
df_reset = df.reset_index()
print(df_reset)
输出:
Letter Number Value 0 A 1 10 1 A 2 20 2 B 1 30 3 B 2 40
6. 多重索引的缺失值
多重索引中的缺失值可以通过 fillna()
或 dropna()
来处理,类似于普通索引。
实例
data = {
'Letter': ['A', 'A', 'B', 'B'],
'Number': [1, 2, 1, 2],
'Value': [10, None, 30, 40]
}
df = pd.DataFrame(data)
df.set_index(['Letter', 'Number'], inplace=True)
# 填充缺失值
df_filled = df.fillna(0)
print(df_filled)
输出:
Value Letter Number A 1 10 2 0 B 1 30 2 40