Pandas学习笔记

本文最后更新于 2025年12月26日 晚上

pandas DataFrame 使用大全

一、创建 DataFrame

1. 从字典创建

1
2
3
4
5
6
7
8
9
10
11
12
13
import pandas as pd
import numpy as np

# 基本字典创建
data = {'A': [1, 2, 3], 'B': [4, 5, 6], 'C': [7, 8, 9]}
df = pd.DataFrame(data)

# 指定行索引
df = pd.DataFrame(data, index=['row1', 'row2', 'row3'])

# 从字典列表创建(每条字典为一列)
data = [{'A': 1, 'B': 2}, {'A': 3, 'B': 4}]
df = pd.DataFrame(data)

2. 从列表创建

1
2
3
4
5
6
7
# 列表的列表(每个子列表为一行)
data = [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
df = pd.DataFrame(data, columns=['A', 'B', 'C'])

# 元组的列表
data = [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
df = pd.DataFrame(data, columns=['A', 'B', 'C'])

3. 从 Series 创建

1
2
3
s1 = pd.Series([1, 2, 3], name='A')
s2 = pd.Series([4, 5, 6], name='B')
df = pd.concat([s1, s2], axis=1)

4. 从 NumPy 数组创建

1
2
arr = np.array([[1, 4], [2, 5], [3, 6]])
df = pd.DataFrame(arr, columns=['A', 'B'])

5. 特殊创建方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 创建空 DataFrame
df_empty = pd.DataFrame()

# 创建重复值的 DataFrame
df_repeat = pd.DataFrame(np.repeat([[1, 2]], 3, axis=0), columns=['A', 'B'])

# 创建随机数据的 DataFrame
df_random = pd.DataFrame(np.random.rand(3, 2), columns=['A', 'B'])

# 创建日期范围作为索引
df_date = pd.DataFrame(
{'A': [1, 2, 3]},
index=pd.date_range('2024-01-01', periods=3)
)

二、访问数据

1. 基本查看

1
2
3
4
5
6
7
8
9
df.head(2)      # 查看前2行
df.tail(2) # 查看后2行
df.sample(2) # 随机查看2行
df.shape # 形状 (行数, 列数)
df.columns # 列名列表
df.index # 索引
df.dtypes # 每列数据类型
df.info() # 详细信息
df.describe() # 统计描述

2. 选择列

1
2
3
4
5
6
7
8
9
10
# 选择单列(返回Series)
df['A']
df.A # 仅当列名是有效Python标识符时可用

# 选择多列(返回DataFrame)
df[['A', 'B']]

# 选择列切片
df.loc[:, 'A':'C'] # 按标签
df.iloc[:, 0:2] # 按位置

3. 选择行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 按标签选择
df.loc['row1'] # 单行
df.loc[['row1', 'row3']] # 多行
df.loc['row1':'row3'] # 行切片(包含结束)

# 按位置选择
df.iloc[0] # 单行
df.iloc[[0, 2]] # 多行
df.iloc[0:3] # 行切片(不包含结束)
df.iloc[-1] # 最后一行

# 按条件选择
df[df['A'] > 2] # 单条件
df[(df['A'] > 1) & (df['B'] < 6)] # 多条件
df[df['A'].isin([1, 3])] # 在列表中
df[~df['A'].isin([1, 3])] # 不在列表中
df[df['A'].between(1, 3)] # 在范围内
df[df['A'].str.contains('text')] # 字符串包含(字符串列)

4. 同时选择行和列

1
2
3
4
5
6
7
8
9
10
11
12
# loc:基于标签
df.loc['row1', 'A'] # 单个值
df.loc[['row1', 'row2'], ['A', 'B']] # 多行多列
df.loc['row1':'row3', 'A':'C'] # 行和列切片

# iloc:基于位置
df.iloc[0, 0] # 单个值
df.iloc[[0, 2], [0, 1]] # 多行多列
df.iloc[0:3, 0:2] # 行和列切片

# 混合使用(ix已弃用)
df.loc[df['A'] > 1, ['B', 'C']] # 条件行,指定列

5. 使用 query 方法

1
2
3
4
df.query('A > 1')
df.query('A > 1 and B < 6')
df.query('A in [1, 3]')
df.query('@variable_name > A') # 使用外部变量

三、删除数据

1. 删除行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 按索引删除
df.drop([0, 2]) # 删除索引为0和2的行
df.drop(index=[0, 2]) # 明确指定删除行
df.drop(['row1', 'row2']) # 按标签名删除

# 按条件删除
df.drop(df[df['A'] < 2].index) # 删除A<2的行
df = df[df['A'] >= 2] # 保留A>=2的行(更常用)

# 删除重复行
df.drop_duplicates() # 删除完全重复的行
df.drop_duplicates(subset=['A']) # 基于A列删除重复
df.drop_duplicates(keep='last') # 保留最后出现的重复

# 删除缺失行
df.dropna() # 删除包含NaN的行
df.dropna(subset=['A']) # 删除A列为NaN的行
df.dropna(thresh=2) # 至少保留2个非NaN值

2. 删除列

1
2
3
4
5
6
7
8
9
10
11
12
13
df.drop('A', axis=1)                # 删除单列
df.drop(['A', 'B'], axis=1) # 删除多列
df.drop(columns=['A', 'B']) # 明确指定删除列

# 按条件删除列
df.dropna(axis=1) # 删除包含NaN的列
df.loc[:, df.columns != 'A'] # 使用loc保留其他列

# 删除所有为NaN的列
df.dropna(axis=1, how='all')

# 删除特定数据类型的列
df.select_dtypes(exclude=['object']) # 选择非对象类型,排除字符串列

3. 重置索引

1
2
df.reset_index(drop=True)           # 重置索引并丢弃原索引
df.reset_index() # 重置索引,原索引变为列

四、修改数据

1. 修改列名

1
2
3
4
df.rename(columns={'A': 'new_A', 'B': 'new_B'})  # 部分重命名
df.columns = ['new_A', 'new_B', 'new_C'] # 全部重命名
df.columns = df.columns.str.upper() # 改为大写
df.columns = df.columns.str.replace('_', ' ') # 替换字符

2. 修改行索引

1
2
3
4
df.index = ['row1', 'row2', 'row3']  # 完全替换
df.rename(index={0: 'row1', 1: 'row2'}) # 部分重命名
df.set_index('A') # 将A列设为索引
df.reset_index() # 重置索引

3. 修改值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 修改单个值
df.at[0, 'A'] = 10 # 按标签(最快)
df.iat[0, 0] = 10 # 按位置

# 修改整列
df['A'] = [10, 20, 30]
df['A'] = df['A'] * 2
df['A'] = df['A'].apply(lambda x: x**2)

# 条件修改
df.loc[df['A'] > 2, 'B'] = 99
df['C'] = np.where(df['A'] > 2, 'high', 'low')

# 使用replace
df.replace(2, 20) # 将2替换为20
df.replace({1: 10, 3: 30}) # 字典替换
df.replace({'A': {1: 10, 3: 30}}) # 指定列替换
df.replace('[a-z]', 'X', regex=True) # 正则替换

4. 添加列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 直接赋值
df['new_col'] = [1, 2, 3]
df['new_col'] = df['A'] + df['B']

# 使用assign(返回新DataFrame)
df = df.assign(new_col = df['A'] + df['B'],
another_col = lambda x: x['A'] * 2)

# 插入列到指定位置
df.insert(1, 'new_col', [1, 2, 3]) # 在第1列位置插入

# 使用条件判断
df['category'] = np.where(df['A'] > 2, 'high', 'low')

# 使用apply
df['squared'] = df['A'].apply(lambda x: x**2)

5. 添加行

1
2
3
4
5
6
7
8
9
# 使用loc
df.loc[len(df)] = [4, 7, 10] # 添加新行

# 使用append(已弃用,建议用concat)
new_row = pd.DataFrame({'A': [4], 'B': [7], 'C': [10]})
df = pd.concat([df, new_row], ignore_index=True)

# 从字典添加
df = df.append({'A': 4, 'B': 7, 'C': 10}, ignore_index=True) # 已弃用

6. 数据类型转换

1
2
3
4
5
df['A'] = df['A'].astype('float')
df = df.astype({'A': 'int32', 'B': 'str'})

# 转换日期
df['date_col'] = pd.to_datetime(df['date_str'])

五、数据操作

1. 排序

1
2
3
4
df.sort_values('A')                     # 按A列升序
df.sort_values('A', ascending=False) # 降序
df.sort_values(['A', 'B']) # 多列排序
df.sort_index() # 按索引排序

2. 分组聚合

1
2
3
4
5
6
7
8
9
10
# 基本分组
df.groupby('A').sum()
df.groupby('A').agg({'B': 'sum', 'C': 'mean'})
df.groupby('A').agg(sum_B=('B', 'sum'), mean_C=('C', 'mean'))

# 多级分组
df.groupby(['A', 'B']).mean()

# 使用transform(保持原形状)
df['group_mean'] = df.groupby('A')['B'].transform('mean')

3. 合并连接

1
2
3
4
5
6
7
8
9
10
11
# concat(拼接)
pd.concat([df1, df2], axis=0) # 纵向拼接
pd.concat([df1, df2], axis=1) # 横向拼接

# merge(类似SQL JOIN)
pd.merge(df1, df2, on='key') # 内连接
pd.merge(df1, df2, on='key', how='left') # 左连接
pd.merge(df1, df2, left_on='key1', right_on='key2') # 不同列名

# join(按索引连接)
df1.join(df2, how='left')

4. 数据透视

1
2
3
4
5
6
7
8
9
# 透视表
df.pivot_table(values='C', index='A', columns='B', aggfunc='mean')

# 交叉表
pd.crosstab(df['A'], df['B'])

# 数据重塑
df.pivot(index='A', columns='B', values='C') # 长变宽
df.melt(id_vars=['A'], value_vars=['B', 'C']) # 宽变长

5. 缺失值处理

1
2
3
4
5
6
7
8
9
10
11
12
# 检查缺失值
df.isnull()
df.isnull().sum()

# 填充缺失值
df.fillna(0) # 用0填充
df.fillna({'A': 0, 'B': df['B'].mean()}) # 不同列不同填充
df.fillna(method='ffill') # 前向填充
df.fillna(method='bfill') # 后向填充
df.interpolate() # 插值填充

# 删除缺失值(见删除部分)

6. 重复值处理

1
2
3
df.duplicated()                       # 检查重复行
df.duplicated(subset=['A', 'B']) # 检查指定列重复
df.drop_duplicates() # 删除重复

六、常用技巧

1. 链式操作

1
2
3
4
(df.query('A > 1')
.sort_values('B')
.assign(new_col=lambda x: x['A'] * 2)
.reset_index(drop=True))

2. 矢量化操作

1
2
3
# 避免使用apply,尽量使用矢量化操作
df['result'] = df['A'] + df['B'] # 推荐
df['result'] = df.apply(lambda row: row['A'] + row['B'], axis=1) # 不推荐

3. 内存优化

1
2
3
4
5
# 查看内存使用
df.memory_usage(deep=True)

# 减少内存使用
df['A'] = df['A'].astype('int32') # 使用更小的数据类型

4. 性能优化

1
2
3
4
5
# 使用query提高查询性能(特别是大数据集)
df.query('A > 1 and B < 5')

# 使用类别数据类型提高字符串性能
df['category_col'] = df['category_col'].astype('category')

七、保存和加载

1
2
3
4
5
6
7
8
9
10
11
# 保存
df.to_csv('data.csv', index=False)
df.to_excel('data.xlsx', index=False)
df.to_json('data.json')
df.to_pickle('data.pkl') # 二进制格式,保存所有信息

# 读取
df = pd.read_csv('data.csv')
df = pd.read_excel('data.xlsx')
df = pd.read_json('data.json')
df = pd.read_pickle('data.pkl')
  1. 使用 lociloc 进行明确的索引访问
  2. 避免链式索引(如 df['A'][0] = 1),使用 df.loc[0, 'A'] = 1
  3. 尽量使用向量化操作而非循环或apply
  4. 注意inplace参数,大多数操作默认返回新DataFrame
  5. 及时释放内存,处理大数据时注意内存管理
  6. 使用query进行复杂筛选,代码更简洁
  7. 保存中间结果,避免重复计算

Pandas学习笔记
https://www.mirstar.net/2025/12/26/pandas-learning-journal/
作者
onlymatt
发布于
2025年12月26日
许可协议