DataFrame 基础 #
什么是 DataFrame? #
DataFrame 是 Pandas 的二维数据结构,类似于 Excel 表格或 SQL 表。它由行索引、列索引和数据组成,每列可以是不同的数据类型。
text
┌─────────────────────────────────────────────────────────────┐
│ DataFrame │
├─────────────────────────────────────────────────────────────┤
│ │
│ name age city salary │
│ 0 Alice 25 New York 50000 │
│ 1 Bob 30 London 60000 │
│ 2 Charlie 35 Tokyo 70000 │
│ 3 Diana 28 Paris 55000 │
│ │
│ 组成: │
│ - 行索引(左侧 0, 1, 2, 3) │
│ - 列索引(name, age, city, salary) │
│ - 数据(每列可以是不同类型) │
│ │
└─────────────────────────────────────────────────────────────┘
创建 DataFrame #
从字典创建 #
python
import pandas as pd
# 字典列表
data = {
'name': ['Alice', 'Bob', 'Charlie'],
'age': [25, 30, 35],
'city': ['New York', 'London', 'Tokyo']
}
df = pd.DataFrame(data)
print(df)
# name age city
# 0 Alice 25 New York
# 1 Bob 30 London
# 2 Charlie 35 Tokyo
# 指定列顺序
df = pd.DataFrame(data, columns=['city', 'name', 'age'])
# 指定索引
df = pd.DataFrame(data, index=['a', 'b', 'c'])
从列表创建 #
python
# 列表的列表
data = [
['Alice', 25, 'New York'],
['Bob', 30, 'London'],
['Charlie', 35, 'Tokyo']
]
df = pd.DataFrame(data, columns=['name', 'age', 'city'])
# 字典列表
data = [
{'name': 'Alice', 'age': 25, 'city': 'New York'},
{'name': 'Bob', 'age': 30, 'city': 'London'},
{'name': 'Charlie', 'age': 35, 'city': 'Tokyo'}
]
df = pd.DataFrame(data)
从 NumPy 数组创建 #
python
import numpy as np
arr = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])
df = pd.DataFrame(arr, columns=['A', 'B', 'C'])
print(df)
# A B C
# 0 1 2 3
# 1 4 5 6
# 2 7 8 9
从 Series 创建 #
python
s1 = pd.Series([1, 2, 3], name='A')
s2 = pd.Series([4, 5, 6], name='B')
# 合并为 DataFrame
df = pd.DataFrame({s1.name: s1, s2.name: s2})
# 或
df = pd.concat([s1, s2], axis=1)
创建空 DataFrame #
python
# 完全空
df = pd.DataFrame()
# 指定列
df = pd.DataFrame(columns=['name', 'age', 'city'])
# 指定列和索引
df = pd.DataFrame(columns=['name', 'age'], index=['a', 'b', 'c'])
DataFrame 属性 #
python
df = pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie'],
'age': [25, 30, 35],
'city': ['New York', 'London', 'Tokyo']
})
# 形状
print(df.shape) # (3, 3)
# 行数和列数
print(len(df)) # 3 行
print(len(df.columns)) # 3 列
# 列名
print(df.columns) # Index(['name', 'age', 'city'], dtype='object')
# 行索引
print(df.index) # RangeIndex(start=0, stop=3, step=1)
# 数据类型
print(df.dtypes)
# 值(NumPy 数组)
print(df.values)
# 转置
print(df.T)
数据查看 #
python
df = pd.DataFrame({
'name': ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve'] * 20,
'age': [25, 30, 35, 28, 32] * 20,
'city': ['New York', 'London', 'Tokyo', 'Paris', 'Berlin'] * 20,
'salary': [50000, 60000, 70000, 55000, 65000] * 20
})
# 查看前几行
print(df.head()) # 默认 5 行
print(df.head(10)) # 前 10 行
# 查看后几行
print(df.tail()) # 默认 5 行
print(df.tail(10)) # 后 10 行
# 随机抽样
print(df.sample(5)) # 随机 5 行
# 数据信息
print(df.info())
# 统计摘要
print(df.describe())
# 查看数据类型
print(df.dtypes)
# 查看内存使用
print(df.memory_usage())
列操作 #
选择列 #
python
# 选择单列
print(df['name']) # 返回 Series
print(df.name) # 返回 Series(列名为有效标识符时)
# 选择多列
print(df[['name', 'age']]) # 返回 DataFrame
print(df.loc[:, ['name', 'age']])
print(df.iloc[:, [0, 1]])
添加列 #
python
# 直接赋值
df['country'] = ['USA', 'UK', 'Japan', 'France', 'Germany'] * 20
# 基于现有列计算
df['annual_salary'] = df['salary'] * 12
# 使用 assign
df = df.assign(
bonus=df['salary'] * 0.1,
total=df['salary'] * 1.1
)
# 插入到指定位置
df.insert(0, 'id', range(len(df)))
修改列 #
python
# 修改列值
df['salary'] = df['salary'] * 1.1 # 加薪 10%
# 修改列名
df = df.rename(columns={'name': 'full_name'})
df.columns = ['id', 'full_name', 'age', 'city', 'salary'] # 全部重命名
# 修改数据类型
df['age'] = df['age'].astype(float)
删除列 #
python
# drop 方法
df = df.drop('id', axis=1) # 删除单列
df = df.drop(['col1', 'col2'], axis=1) # 删除多列
# del 关键字
del df['id']
# pop 方法(返回被删除的列)
col = df.pop('salary')
行操作 #
选择行 #
python
# 通过标签
print(df.loc[0]) # 单行
print(df.loc[[0, 1, 2]]) # 多行
print(df.loc[0:2]) # 切片
# 通过位置
print(df.iloc[0]) # 单行
print(df.iloc[[0, 1, 2]]) # 多行
print(df.iloc[0:3]) # 切片
# 条件选择
print(df[df['age'] > 30])
print(df.query('age > 30'))
添加行 #
python
# 使用 loc
df.loc[len(df)] = ['Frank', 40, 'Sydney', 80000]
# 使用 concat
new_row = pd.DataFrame([['Frank', 40, 'Sydney', 80000]], columns=['name', 'age', 'city', 'salary'])
df = pd.concat([df, new_row], ignore_index=True)
# 使用 append(已弃用,建议用 concat)
删除行 #
python
# 通过标签
df = df.drop(0) # 删除单行
df = df.drop([0, 1, 2]) # 删除多行
# 通过条件
df = df[df['age'] > 25] # 保留 age > 25 的行
df = df.drop(df[df['age'] < 30].index) # 删除 age < 30 的行
数据选择详解 #
loc - 标签选择 #
python
# 选择行
df.loc[0] # 单行
df.loc[0:2] # 多行(切片,包含结束)
df.loc[[0, 2, 4]] # 多行(列表)
# 选择列
df.loc[:, 'name'] # 单列
df.loc[:, ['name', 'age']] # 多列
# 同时选择行列
df.loc[0, 'name'] # 单个值
df.loc[0:2, 'name'] # 行切片 + 单列
df.loc[0:2, ['name', 'age']] # 行切片 + 多列
df.loc[df['age'] > 30, 'name'] # 条件 + 列
iloc - 位置选择 #
python
# 选择行
df.iloc[0] # 单行
df.iloc[0:3] # 多行(切片,不包含结束)
df.iloc[[0, 2, 4]] # 多行(列表)
# 选择列
df.iloc[:, 0] # 单列
df.iloc[:, [0, 1]] # 多列
df.iloc[:, 0:2] # 列切片
# 同时选择行列
df.iloc[0, 0] # 单个值
df.iloc[0:3, 0] # 行切片 + 单列
df.iloc[0:3, [0, 1]] # 行切片 + 多列
df.iloc[0:3, 0:2] # 行切片 + 列切片
at / iat - 快速访问单个值 #
python
# at - 标签访问
print(df.at[0, 'name']) # 比 loc 更快
# iat - 位置访问
print(df.iat[0, 0]) # 比 iloc 更快
常用方法 #
统计方法 #
python
# 描述统计
print(df.describe()) # 数值列统计
print(df.describe(include='all')) # 所有列
# 聚合函数
print(df.sum()) # 求和
print(df.mean()) # 平均值
print(df.median()) # 中位数
print(df.std()) # 标准差
print(df.var()) # 方差
print(df.min()) # 最小值
print(df.max()) # 最大值
# 相关性
print(df.corr()) # 相关系数矩阵
print(df.cov()) # 协方差矩阵
排序 #
python
# 按值排序
df = df.sort_values('age') # 单列升序
df = df.sort_values('age', ascending=False) # 单列降序
df = df.sort_values(['age', 'salary']) # 多列排序
# 按索引排序
df = df.sort_index()
df = df.sort_index(axis=1) # 按列名排序
去重 #
python
# 行去重
df = df.drop_duplicates()
# 列去重
df = df.drop_duplicates(subset=['name'])
# 保留最后一个
df = df.drop_duplicates(keep='last')
# 查看重复
print(df.duplicated())
缺失值处理 #
python
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]
})
# 检测缺失值
print(df.isna())
print(df.isna().sum()) # 每列缺失值数量
# 删除缺失值
df = df.dropna() # 删除包含缺失值的行
df = df.dropna(axis=1) # 删除包含缺失值的列
df = df.dropna(how='all') # 只删除全为缺失值的行
df = df.dropna(subset=['A']) # 只考虑指定列
# 填充缺失值
df = df.fillna(0) # 用 0 填充
df = df.fillna({'A': 0, 'B': 1}) # 不同列用不同值
df = df.fillna(df.mean()) # 用均值填充
df = df.ffill() # 前向填充
df = df.bfill() # 后向填充
数据类型转换 #
python
# 单列转换
df['age'] = df['age'].astype(float)
# 多列转换
df = df.astype({'age': 'int32', 'salary': 'float32'})
# 转换为字符串
df['name'] = df['name'].astype(str)
# 智能转换
df = df.convert_dtypes()
DataFrame 运算 #
算术运算 #
python
# 与标量运算
df = df + 10
df['salary'] = df['salary'] * 1.1
# DataFrame 之间运算
df1 = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
df2 = pd.DataFrame({'A': [10, 20, 30], 'B': [40, 50, 60]})
print(df1 + df2)
print(df1.add(df2))
print(df1.sub(df2))
print(df1.mul(df2))
print(df1.div(df2))
比较运算 #
python
# 与标量比较
print(df['age'] > 30)
# DataFrame 之间比较
print(df1.eq(df2))
print(df1.ne(df2))
print(df1.gt(df2))
print(df1.lt(df2))
应用函数 #
python
# apply - 逐列或逐行应用
df.apply(lambda x: x.max() - x.min()) # 默认逐列
df.apply(lambda x: x.max() - x.min(), axis=1) # 逐行
# applymap - 逐元素应用(已弃用,使用 map)
df.map(lambda x: x * 2 if isinstance(x, (int, float)) else x)
# 对单列应用函数
df['name'].str.upper()
df['age'].apply(lambda x: x * 2)
实用技巧 #
条件赋值 #
python
# 使用 loc
df.loc[df['age'] > 30, 'category'] = 'senior'
df.loc[df['age'] <= 30, 'category'] = 'junior'
# 使用 numpy.where
import numpy as np
df['category'] = np.where(df['age'] > 30, 'senior', 'junior')
分组标记 #
python
# 使用 cut
df['age_group'] = pd.cut(df['age'], bins=[0, 25, 35, 100], labels=['young', 'middle', 'senior'])
# 使用 qcut(等频分箱)
df['salary_quartile'] = pd.qcut(df['salary'], q=4, labels=['Q1', 'Q2', 'Q3', 'Q4'])
方法链 #
python
result = (df
.query('age > 25')
.assign(salary_annual=lambda x: x['salary'] * 12)
.sort_values('salary', ascending=False)
.head(10)
)
下一步 #
掌握了 DataFrame 基础后,接下来学习 数据类型,深入了解 Pandas 的数据类型系统!
最后更新:2026-04-04