Pandas 常用函数详解
Pandas 常用函数详解
1. 数据创建和查看函数
1.1 创建数据
import pandas as pd
import numpy as np
# 从各种数据源创建
df_dict = pd.DataFrame({
'A': [1, 2, 3, 4],
'B': [10, 20, 30, 40],
'C': ['a', 'b', 'c', 'd']
})
# 空DataFrame
df_empty = pd.DataFrame(columns=['col1', 'col2'])
# 指定索引
df_indexed = pd.DataFrame(df_dict, index=['w', 'x', 'y', 'z'])
# 从Series创建
s = pd.Series([1, 2, 3])
df_from_series = pd.DataFrame({'col': s})
# 生成测试数据
dates = pd.date_range('20230101', periods=6)
df_test = pd.DataFrame(np.random.randn(6, 4),
index=dates,
columns=list('ABCD'))
1.2 数据查看
# 基本查看
print(df.head(3)) # 前3行
print(df.tail(2)) # 后2行
print(df.sample(5)) # 随机5行
print(df.info()) # 数据信息
print(df.describe()) # 描述性统计
# 形状和结构
print(df.shape) # (行, 列)
print(df.columns) # 列名
print(df.index) # 索引
print(df.dtypes) # 数据类型
print(df.values) # 底层numpy数组
# 转置
print(df.T)
# 内存使用
print(df.memory_usage(deep=True))
2. 选择和索引函数
2.1 基本选择
# 列选择
col_series = df['A'] # 单列(Series)
col_df = df[['A', 'B']] # 多列(DataFrame)
df['new_col'] = df['A'] + df['B'] # 新列
# 行选择
first_row = df.iloc[0] # 位置索引
labeled_row = df.loc['w'] # 标签索引
rows_slice = df.iloc[1:3] # 切片
specific_rows = df.loc[['w', 'y']]
# 混合选择
subset = df.loc['w':'y', ['A', 'C']] # 行标签+列标签
pos_subset = df.iloc[0:2, [0, 2]] # 位置+位置
2.2 条件选择
# 布尔索引
high_a = df[df['A'] > 0]
not_null = df[df['B'].notnull()]
multiple = df[(df['A'] > 0) & (df['B'] < 20)]
# isin方法
in_values = df[df['C'].isin(['a', 'c'])]
not_in = df[~df['C'].isin(['b', 'd'])]
# query方法(字符串条件)
result = df.query('A > 0 and B < 20')
result2 = df.query('A > @threshold') # 使用变量
# between方法
in_range = df[df['A'].between(1, 3)]
# 字符串条件
string_cond = df[df['C'].str.startswith('a')]
2.3 高级索引
# 多级索引
arrays = [np.array(['A', 'A', 'B', 'B']), np.array(['one', 'two', 'one', 'two'])]
index = pd.MultiIndex.from_arrays(arrays, names=('first', 'second'))
df_multi = pd.DataFrame(np.random.randn(4, 2), index=index, columns=['X', 'Y'])
# 多级索引操作
print(df_multi.loc['A']) # 选择第一级
print(df_multi.loc[('A', 'one')]) # 具体组合
print(df_multi.xs('one', level=1)) # 交叉截面
# stack和unstack
stacked = df_multi.stack()
unstacked = stacked.unstack()
3. 数据操作函数
3.1 添加和删除
# 添加列
df['A_squared'] = df['A'] ** 2
df['category'] = pd.cut(df['A'], bins=3) # 分箱
df.assign(new_col=lambda x: x['A'] * 2) # 非原地
# 添加行
new_row = pd.DataFrame({'A': [5], 'B': [50], 'C': ['e']}, index=['new'])
df_appended = pd.concat([df, new_row])
# 删除
df_dropped_cols = df.drop(['A_squared'], axis=1)
df_dropped_rows = df.drop(['w'], axis=0)
df_popped = df.pop('C') # 返回删除的列(Series)
# 重命名
df_renamed = df.rename(columns={'A': 'value1', 'B': 'value2'})
df_index_renamed = df.rename(index={'w': 'row1'})
3.2 排序
# 按值排序
df_sorted_values = df.sort_values('A', ascending=False)
df_multi_sort = df.sort_values(['A', 'B'], ascending=[True, False])
# 按索引排序
df_sorted_index = df.sort_index(ascending=False)
df_sorted_both = df.sort_index(axis=1).sort_index(axis=0)
# 稳定排序
df_stable = df.sort_values('A', kind='stable')
4. 缺失值处理函数
# 检测
has_missing = df.isnull().any().any()
missing_count = df.isnull().sum()
missing_rate = df.isnull().mean()
# 填充
df_filled_mean = df.fillna(df.mean(numeric_only=True))
df_filled_forward = df.fillna(method='ffill')
df_filled_value = df.fillna({'A': 0, 'B': 'missing'})
# 高级填充
df_group_filled = df.groupby('category')['A'].fillna(
df.groupby('category')['A'].transform('mean')
)
# 插值
df_interpolated = df.interpolate(method='linear')
time_interpolated = df.interpolate(method='time') # 需要DatetimeIndex
# 删除
df_dropped = df.dropna()
df_thresh = df.dropna(thresh=3) # 至少3个非空值
df_subset_drop = df.dropna(subset=['A', 'B'])
5. 字符串操作函数
# 字符串方法(.str访问器)
df['C_upper'] = df['C'].str.upper()
df['C_length'] = df['C'].str.len()
df['C_contains'] = df['C'].str.contains('a')
df['C_replace'] = df['C'].str.replace('a', 'A')
df['C_split'] = df['C'].str.split('').str[0] # 错误,应使用expand=True
# 提取和匹配
df['first_letter'] = df['C'].str[0]
df['pattern'] = df['C'].str.extract(r'([a-z])')
df['match'] = df['C'].str.match(r'^a')
# 高级字符串操作
df['padded'] = df['C'].str.zfill(3) # 补零
df['title_case'] = df['C'].str.title()
df['words'] = df['description'].str.split(expand=True) # 分词到列
# 正则表达式
df['phone_clean'] = df['phone'].str.replace(r'[^\d+]', '', regex=True)
df['email_domain'] = df['email'].str.extract(r'@([\w.-]+)', expand=False)
6. 合并和连接函数
6.1 连接(concat)
# 行连接
df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
df2 = pd.DataFrame({'A': [5, 6], 'B': [7, 8]})
concat_rows = pd.concat([df1, df2], ignore_index=True)
# 列连接
concat_cols = pd.concat([df1, df2], axis=1)
# 多级索引连接
concat_keys = pd.concat([df1, df2], keys=['x', 'y'])
# 内连接列
concat_inner = pd.concat([df1, df2], axis=1, join='inner')
6.2 合并(merge)
# 基本合并
left = pd.DataFrame({'key': ['K0', 'K1'], 'A': [1, 2]})
right = pd.DataFrame({'key': ['K0', 'K2'], 'B': [3, 4]})
# 内连接
merged_inner = pd.merge(left, right, on='key', how='inner')
# 左连接
merged_left = pd.merge(left, right, on='key', how='left')
# 多键合并
df1 = pd.DataFrame({'lkey': ['a', 'b'], 'value': [1, 2]})
df2 = pd.DataFrame({'rkey': ['a', 'c'], 'value': [3, 4]})
merged_multi = pd.merge(df1, df2, left_on='lkey', right_on='rkey')
# 指标前缀
merged_prefix = pd.merge(left, right, on='key', suffixes=('_left', '_right'))
6.3 连接(join)
# 基于索引连接
left_idx = left.set_index('key')
right_idx = right.set_index('key')
joined = left_idx.join(right_idx, how='inner')
# 多表连接
df1_idx = df1.set_index('id')
df2_idx = df2.set_index('id')
df3_idx = df3.set_index('id')
result = df1_idx.join([df2_idx, df3_idx], how='outer')
7. 分组和聚合函数
7.1 基本分组
df_group = pd.DataFrame({
'category': ['A', 'A', 'B', 'B', 'A'],
'value1': [1, 2, 3, 4, 5],
'value2': [10, 20, 30, 40, 50]
})
# 基本分组
grouped = df_group.groupby('category')
print(grouped.groups) # 分组信息
print(grouped.size()) # 每组大小
# 聚合
mean_vals = grouped.mean()
sum_vals = grouped['value1'].sum()
7.2 多函数聚合
# 多个聚合函数
agg_result = grouped.agg({
'value1': ['sum', 'mean', 'std'],
'value2': ['min', 'max']
})
# 重命名结果
agg_named = grouped.agg(
value1_sum=('value1', 'sum'),
value1_mean=('value1', 'mean'),
value2_max=('value2', 'max')
)
# 自定义聚合
def range_func(x):
return x.max() - x.min()
custom_agg = grouped.agg({
'value1': ['sum', range_func],
'value2': 'count'
})
7.3 分组转换和过滤
# transform(保持形状)
df['value1_rank'] = grouped['value1'].transform('rank')
df['value1_mean'] = grouped['value1'].transform('mean')
# filter(筛选组)
def filter_large(group):
return len(group) >= 2
filtered = grouped.filter(filter_large)
# apply(灵活操作)
def summarize(group):
return pd.DataFrame({
'count': len(group),
'mean': group['value1'].mean()
})
applied = grouped.apply(summarize)
8. 重塑函数
8.1 透视表
# 简单透视
pivot_simple = df.pivot(index='date', columns='category', values='value')
# 聚合透视
pivot_table = df.pivot_table(values='value',
index='date',
columns='category',
aggfunc='sum',
fill_value=0,
margins=True) # 添加总计
# 多级透视
pivot_multi = df.pivot_table(values='sales',
index=['region', 'product'],
columns='year',
aggfunc='sum')
8.2 melt和wide_to_long
# 宽格式转长格式
wide_df = pd.DataFrame({
'id': [1, 2],
'year_2021': [100, 200],
'year_2022': [150, 250]
})
long_df = pd.melt(wide_df,
id_vars=['id'],
value_vars=['year_2021', 'year_2022'],
var_name='year',
value_name='sales')
# 自动识别
long_auto = pd.wide_to_long(wide_df,
stubnames='year',
i='id',
j='year_type',
sep='_',
suffix='\d+')
8.3 stack和unstack
# 多级索引
multi_idx = pd.MultiIndex.from_product([['A', 'B'], ['X', 'Y']])
df_multi = pd.DataFrame(np.random.randn(4, 4),
index=multi_idx,
columns=['P', 'Q', 'R', 'S'])
# stack(列转行)
stacked = df_multi.stack()
double_stacked = df_multi.stack([0, 1])
# unstack(行转列)
unstacked = stacked.unstack()
partial_unstack = stacked.unstack(0) # 指定级别
9. 统计函数
9.1 描述性统计
# 基本统计
print(df.mean()) # 均值
print(df.median()) # 中位数
print(df.std()) # 标准差
print(df.var()) # 方差
print(df.min()) # 最小值
print(df.max()) # 最大值
print(df.sum()) # 总和
print(df.count()) # 非空计数
print(df.quantile([0.25, 0.5, 0.75])) # 分位数
# 相关性
corr_matrix = df.corr() # 相关系数矩阵
corr_pairs = df.corrwith(df['A']) # 与A的相关性
# 协方差
cov_matrix = df.cov()
9.2 滚动统计
# 需要时间索引或数值索引
df_time = df_test.copy()
df_time.index = pd.date_range('2023-01-01', periods=6, freq='D')
# 滚动窗口
rolling_mean = df_time['A'].rolling(window=3).mean()
rolling_sum = df_time['A'].rolling(window=3, min_periods=1).sum()
# 扩展窗口
expanding_mean = df_time['A'].expanding().mean()
expanding_max = df_time['A'].expanding(min_periods=2).max()
# 自定义窗口
custom_window = df_time['A'].rolling('2D').mean() # 时间窗口
9.3 排名和分位
# 排名
df['A_rank'] = df['A'].rank() # 升序排名
df['A_rank_desc'] = df['A'].rank(ascending=False) # 降序排名
df['dense_rank'] = df['A'].rank(method='dense') # 密集排名
df['min_rank'] = df['A'].rank(method='min') # 最小排名
# 分位数
df['A_quantile'] = pd.qcut(df['A'], q=4, labels=['Q1', 'Q2', 'Q3', 'Q4'])
df['A_percentile'] = df['A'].rank(pct=True) # 百分位排名
10. 时间序列函数
# 创建时间索引
dates = pd.date_range('2023-01-01', periods=100, freq='D')
ts_df = pd.DataFrame(np.random.randn(100, 2),
index=dates,
columns=['A', 'B'])
# 时间属性
ts_df['year'] = ts_df.index.year
ts_df['month'] = ts_df.index.month
ts_df['weekday'] = ts_df.index.day_name()
ts_df['quarter'] = ts_df.index.quarter
# 重采样
monthly = ts_df.resample('M').mean()
quarterly = ts_df.resample('Q').sum()
# 移位和滞后
ts_df['A_lag1'] = ts_df['A'].shift(1)
ts_df['A_lead1'] = ts_df['A'].shift(-1)
ts_df['A_diff'] = ts_df['A'].diff() # 一阶差分
ts_df['A_pct'] = ts_df['A'].pct_change() # 变化率
# 滚动时间窗口
weekly_rolling = ts_df['A'].rolling('7D').mean()
monthly_rolling = ts_df['A'].rolling('30D').sum()
11. 输入输出函数
11.1 CSV操作
# 读取
df_csv = pd.read_csv('data.csv',
encoding='utf-8',
parse_dates=['date'],
dtype={'id': 'int32', 'category': 'category'})
# 写入
df_csv.to_csv('output.csv',
index=False,
encoding='utf-8',
date_format='%Y-%m-%d')
11.2 Excel操作
# 读取
df_excel = pd.read_excel('data.xlsx',
sheet_name='Sheet1',
usecols='A:C')
# 多工作表写入
with pd.ExcelWriter('output.xlsx') as writer:
df1.to_excel(writer, sheet_name='数据1', index=False)
df2.to_excel(writer, sheet_name='数据2', index=False)
11.3 其他格式
# JSON
df.to_json('data.json', orient='records', indent=2)
df_json = pd.read_json('data.json')
# SQL
from sqlalchemy import create_engine
engine = create_engine('sqlite:///database.db')
df.to_sql('table_name', engine, if_exists='replace')
df_sql = pd.read_sql('SELECT * FROM table_name', engine)
# Pickle(二进制)
df.to_pickle('data.pkl')
df_pickle = pd.read_pickle('data.pkl')
# Parquet(高效列式存储)
df.to_parquet('data.parquet', compression='snappy')
df_parquet = pd.read_parquet('data.parquet')
12. 实用工具函数
12.1 数据转换
# 数值转换
pd.to_numeric(df['col'], errors='coerce') # 字符串转数值
pd.to_datetime(df['date'], format='%Y-%m-%d') # 字符串转日期
# 类别转换
pd.Categorical(df['col']) # 分类类型
pd.get_dummies(df['category'], prefix='cat') # 独热编码
# 标准化/归一化
from sklearn.preprocessing import StandardScaler, MinMaxScaler
scaler = StandardScaler()
df['A_scaled'] = scaler.fit_transform(df[['A']])
# 字符串处理
pd.Series(['apple', 'banana']).str.lower()
pd.Series(['a,b,c']).str.split(',').str[0]
12.2 实用函数
# 唯一值和频数
print(df['C'].unique())
print(df['C'].nunique())
print(df['C'].value_counts())
# 查找位置
print(df['A'].idxmax()) # 最大值位置
print(df['A'].idxmin()) # 最小值位置
# 剪切和限制
df['A_clipped'] = df['A'].clip(lower=0, upper=10)
# 取样
df_sample = df.sample(frac=0.1, random_state=42) # 10%样本
df_sample_n = df.sample(n=5, replace=True) # 有放回抽样
# 连接字符串
pd.concat([s1, s2], axis=1) # 列连接
s1.combine(s2, lambda x1, x2: x1 if pd.notna(x1) else x2) # 组合
12.3 性能和诊断
# 性能分析
%timeit df['A'].mean() # Jupyter时间测试
# 内存优化
df_optimized = df.copy()
for col in df.select_dtypes(['object']).columns:
if df[col].nunique() < len(df) * 0.5:
df_optimized[col] = df[col].astype('category')
# 进度条(大操作)
from tqdm import tqdm
tqdm.pandas()
df['processed'] = df['text'].progress_apply(lambda x: x.upper())
# 复制和视图
df_copy = df.copy(deep=True) # 深拷贝
df_view = df[:] # 浅拷贝/视图
13. 实际应用组合示例
# 完整数据处理流程
def complete_data_pipeline(df):
"""完整的数据处理示例"""
# 1. 数据清洗
df_clean = df.dropna(thresh=len(df.columns)*0.8)
df_clean = df_clean.drop_duplicates()
# 2. 类型转换
numeric_cols = df_clean.select_dtypes(include=['object']).columns
for col in numeric_cols:
df_clean[col] = pd.to_numeric(df_clean[col], errors='coerce')
# 3. 创建特征
if 'date' in df_clean.columns:
df_clean['year'] = pd.to_datetime(df_clean['date']).dt.year
df_clean['month'] = pd.to_datetime(df_clean['date']).dt.month
# 4. 分组统计
if 'category' in df_clean.columns:
group_stats = df_clean.groupby('category').agg({
'value': ['mean', 'sum', 'count']
})
group_stats.columns = ['mean_value', 'sum_value', 'count']
# 5. 透视分析
pivot = df_clean.pivot_table(values='value',
index='category',
columns='year',
aggfunc='sum')
# 6. 排名和分位
df_clean['value_rank'] = df_clean['value'].rank()
df_clean['value_quantile'] = pd.qcut(df_clean['value'], q=4)
return df_clean, group_stats, pivot
# 使用
df_processed, stats, pivot = complete_data_pipeline(df)
14. 调试和最佳实践
14.1 常见模式
# 链式操作
result = (df
.query('A > 0')
.groupby('category')
.agg({'B': 'mean'})
.reset_index()
.sort_values('B', ascending=False))
# 方法链最佳实践
(df.pipe(lambda x: x.dropna())
.assign(new_col=lambda x: x['A'] * 2)
.query('new_col > 10')
)
# 错误处理
try:
result = df.groupby('nonexistent_col').mean()
except KeyError as e:
print(f"列不存在: {e}")
# 处理逻辑
14.2 性能提示
# 避免
for i in range(len(df)):
df.iloc[i] = some_calculation()
# 推荐
df['new_col'] = df['A'].apply(some_calculation) # 仍然较慢
df['new_col'] = np.where(df['A'] > 0, df['A']*2, 0) # 向量化
# 大数据处理
def process_chunks(file_path, func, chunk_size=10000):
chunks = []
for chunk in pd.read_csv(file_path, chunksize=chunk_size):
processed = func(chunk)
chunks.append(processed)
return pd.concat(chunks, ignore_index=True)
这些常用函数构成了Pandas的核心能力,熟练掌握它们可以处理绝大多数数据分析任务。建议结合实际项目练习,理解每个函数的适用场景和性能特性。