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