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
|
添加后缀,以区分重复的列名 |
import pandas as pd# 示例数据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
|
为合并的对象提供层次化索引 |
importpandasaspd# 示例数据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
|
使用的连接列,默认基于索引 |
importpandasaspd# 示例数据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
|
填充缺失值 |
importpandasaspd# 示例数据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
|
importpandasaspd# 示例数据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
|
importpandasaspd# 示例数据df=pd.DataFrame({'A':[1,2,3,4],'B':[10,20,30,40]})# 定义自定义函数defcustom_func(x):returnx *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
|
需要应用的函数 |
importpandasaspd# 示例数据df=pd.DataFrame({'A':[1,2,3],'B':[4,5,6]})# 在 DataFrame 上应用自定义函数df=df.applymap(lambdax: x **2)print(df)
输出:
A B 0 1 16 1 4 25 2 9 36
3.
map()
— 应用函数到 Series 上
map()
可以对 Series 中的每个元素应用一个函数或一个映射关系。
| 参数 | 说明 |
|---|---|
arg
|
应用的函数,字典或 Series |
importpandasaspd# 示例数据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) |
importpandasaspd# 示例数据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
|
聚合函数,可以是字符串或自定义函数 |
importpandasaspd# 示例数据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
表示小时等)
|
importpandasaspd# 生成时间序列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()
可以进行时间的加减操作。
importpandasaspd# 日期偏移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()
|
计算扩展窗口操作,累计值 |
importpandasaspd# 示例数据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()
|
删除包含缺失值的行或列 |
importpandasaspdimportnumpyasnp# 示例数据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
|
每个索引级别的名称(可选) |
importpandasaspd# 创建元组index_tuples=[('A',1),('A',2),('B',1),('B',2)]# 创建多重索引multi_index=pd.MultiIndex.from_tuples(index_tuples,names=['Letter','Number'])# 创建 DataFramedf=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
|
每个索引级别的名称(可选) |
importpandasaspd# 创建多个列表index_values=[['A','B'],[1,2]]# 创建多重索引multi_index=pd.MultiIndex.from_product(index_values,names=['Letter','Number'])# 创建 DataFramedf=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
|
用作索引的列名(可以是单列或多列) |
importpandasaspd# 示例数据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[]
选择数据:
importpandasaspd# 示例数据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()
方法可以在多重索引中选择指定级别的切片。
# 使用 xs 获取 'Number' 为 1 的所有数据print(df.xs(1,level='Number'))
输出:
Value
Letter
A 10
B 30
2. 多重索引的切片
Pandas 支持对多重索引进行切片操作,允许通过索引级别选择不同的子集。
# 选择 Letter 为 'A' 的所有数据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()
可以进行强大的聚合操作,适用于复杂数据的统计分析。
# 使用 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