RSS
菜单
全部文章快讯开发科技深度热点

第 3 章 DataFrame 详解

内容摘要

本篇文章全面讲解 pandas 最核心的二维数据结构 **DataFrame**:创建方式、结构组成、常用属性、行列操作、增删改查。学完本章,你将能够熟练地在内存中"搭建和摆弄"一张表格。

本篇文章全面讲解 pandas 最核心的二维数据结构 DataFrame:创建方式、结构组成、常用属性、行列操作、增删改查。学完本章,你将能够熟练地在内存中"搭建和摆弄"一张表格。

目录

1. 什么是 DataFrame

2. 创建 DataFrame 的 6 种方式

3. DataFrame 的组成结构

4. 常用属性

5. 查看数据概览

6. 行列的增删改

7. DataFrame 与 Series 的相互转换

8. DataFrame 的运算

9. 转置与轴向操作

10. 常见坑与注意事项

11. 本章小结与练习


1. 什么是 DataFrame

DataFrame 是 pandas 的二维表格型数据结构,可以理解成"一张带行索引和列名的 Excel 工作表"。

特点:

  • 有行索引(index)和列名(columns);
  • 每一列本质上是一个 Series(共享同一行索引);
  • 各列类型可以不同(一列是整数、一列是字符串、一列是日期);
  • 支持丰富的行/列操作、分组聚合、合并、透视等高级功能。
           姓名    年龄   城市
id=1       张三     25   北京
id=2       李四     30   上海
id=3       王五     28   广州

2. 创建 DataFrame 的 6 种方式

2.1 从字典创建(最常用)

import pandas as pd

df = pd.DataFrame({
    "姓名": ["张三", "李四", "王五"],
    "年龄": [25, 30, 28],
    "城市": ["北京", "上海", "广州"],
})
print(df)
   姓名  年龄  城市
0  张三  25  北京
1  李四  30  上海
2  王五  28  广州
  • 字典的键成为列名;
  • 每个值(列表)成为一列数据;
  • 默认行索引为 0,1,2...

2.2 从列表的列表 / 元组创建

df2 = pd.DataFrame(
    [["张三", 25, "北京"],
     ["李四", 30, "上海"],
     ["王五", 28, "广州"]],
    columns=["姓名", "年龄", "城市"],
)
print(df2)

2.3 从 NumPy 数组创建

import numpy as np

arr = np.random.randint(0, 100, size=(4, 3))
df3 = pd.DataFrame(arr, columns=["语文", "数学", "英语"])
print(df3)

2.4 从 Series 字典创建

df4 = pd.DataFrame({
    "a": pd.Series([1, 2, 3]),
    "b": pd.Series([10, 20]),
})
print(df4)
#      a     b
# 0    1  10.0
# 1    2  20.0
# 2    3   NaN
两个 Series 长度不一致时,缺失位置自动补 NaN。

2.5 从列表的字典(每条记录一个字典)

records = [
    {"姓名": "张三", "年龄": 25},
    {"姓名": "李四", "年龄": 30, "城市": "上海"},
]
df5 = pd.DataFrame(records)
print(df5)
#    姓名   年龄    城市
# 0  张三  25.0   NaN
# 1  李四  30.0   上海

2.6 从 CSV / Excel 等文件读取

df6 = pd.read_csv("data.csv")
df7 = pd.read_excel("data.xlsx", sheet_name="Sheet1")

(详细读写知识见第 4 章)

创建方式速查表

| 数据源 | 写法 | 特点 |

|--------|------|------|

| 字典 | pd.DataFrame({列: 列表}) | 最直观,键为列名 |

| 列表的列表 | pd.DataFrame([...], columns=[...]) | 需手动指定列名 |

| ndarray | pd.DataFrame(arr, columns=[...]) | 适合程序化生成 |

| Series 字典 | pd.DataFrame({"a": s1, "b": s2}) | 索引自动对齐 |

| 记录列表 | pd.DataFrame([{...}, {...}]) | 适合 API 返回数据 |

| 文件 | pd.read_csv/excel/json | 最常用 |


3. DataFrame 的组成结构

一个 DataFrame 由三部分组成:

df = pd.DataFrame(
    {"姓名": ["张三", "李四"], "年龄": [25, 30]},
    index=["r1", "r2"],
)
print(df)
#     姓名  年龄
# r1  张三  25
# r2  李四  30

# 三部分
print(df.index)      # Index(['r1', 'r2'], dtype='object')     行索引
print(df.columns)    # Index(['姓名', '年龄'], dtype='object') 列名
print(df.values)     # [['张三' 25] ['李四' 30]]                数据(ndarray)
values 是所有列拼成的二维 NumPy 数组,混合类型时 dtype 会变成 object。

4. 常用属性

import pandas as pd

df = pd.DataFrame({
    "姓名": ["张三", "李四", "王五"],
    "年龄": [25, 30, 28],
    "城市": ["北京", "上海", "广州"],
})

print(df.shape)          # (3, 3)  行数、列数
print(df.size)           # 9  元素总数
print(df.ndim)           # 2  维度
print(df.dtypes)         # 每列类型(注意是 dtypes 复数)
print(df.index)          # 行索引
print(df.columns)        # 列名
print(df.values)         # 数据数组
print(df.empty)          # False
print(df.axes)           # [行索引, 列名] 列表
print(df.T)              # 转置
print(df.memory_usage()) # 每列内存占用

df.dtypes 输出:

姓名    object
年龄     int64
城市    object
dtype: object

单列与多列访问

# 取一列 -> Series
age = df["年龄"]
print(type(age))        # <class 'pandas.core.series.Series'>

# 取多列 -> DataFrame
sub = df[["姓名", "城市"]]
print(type(sub))        # <class 'pandas.core.frame.DataFrame'>

5. 查看数据概览

# 前几行 / 后几行
print(df.head(2))        # 前 2 行
print(df.tail(2))        # 后 2 行

# 随机抽样
print(df.sample(2))

# 基本信息(列名、非空计数、类型)
print(df.info())

# 数值列统计摘要
print(df.describe())

# 每列唯一值个数
print(df.nunique())

# 每列缺失值个数
print(df.isna().sum())

describe() 输出:

            年龄
count   3.000000
mean   27.666667
std     2.516611
min    25.000000
25%    26.500000
50%    28.000000
75%    29.000000
max    30.000000
describe(include="object") 可以查看字符串列的统计(count、unique、top、freq)。

6. 行列的增删改

6.1 新增列

# 直接赋值新列
df["部门"] = ["技术", "销售", "市场"]
print(df.columns)   # Index(['姓名', '年龄', '城市', '部门'], ...)

# 用已有列计算新列
df["明年年龄"] = df["年龄"] + 1

# 用条件生成列
df["是否成年"] = df["年龄"] >= 18

# 用 assign 生成(不修改原表,返回新表)
df2 = df.assign(年龄平方=df["年龄"] ** 2)

6.2 删除列

# 删除列(axis=1),inplace 表示原地修改
df = df.drop("明年年龄", axis=1)
# 等价写法
df = df.drop(columns=["是否成年"])

# 删除行
df = df.drop(0)                 # 删除索引为 0 的行
df = df.drop([1, 2])            # 删除多行
重要:drop 默认返回新对象,不修改原表。想原地修改需 inplace=True,但官方推荐的做法是直接重新赋值(如 df = df.drop(...))。

6.3 修改数据

# 修改单个值(推荐 .at / .loc)
df.at[0, "年龄"] = 26
df.loc[1, "城市"] = "深圳"

# 修改整列
df["年龄"] = [26, 31, 29]

# 按条件批量修改
df.loc[df["年龄"] > 28, "备注"] = "资深"

6.4 重命名

# 重命名列
df = df.rename(columns={"姓名": "name", "年龄": "age"})

# 重命名索引
df = df.rename(index={0: "第一行"})

7. DataFrame 与 Series 的相互转换

# DataFrame -> 取列得 Series
s = df["年龄"]

# DataFrame -> 取一行得 Series(索引为列名)
row = df.loc[0]

# DataFrame -> 字典 {列名: Series}
d = df.to_dict()

# DataFrame -> 列表的列表
lst = df.values.tolist()

# Series -> DataFrame
s_df = s.to_frame(name="年龄")

# Series -> 字典 / 列表
print(s.to_dict())
print(s.to_list())

8. DataFrame 的运算

8.1 列与列的运算

df["总价"] = df["单价"] * df["数量"]      # 向量化逐行运算
df["折扣价"] = df["总价"] * 0.9

8.2 行/列方向的统计(axis 参数)

import numpy as np

df = pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6], "c": [7, 8, 9]})

# 默认 axis=0:按列统计(对每列求)
print(df.sum())          # a=6  b=15  c=24
print(df.mean(axis=0))   # 每列均值

# axis=1:按行统计(对每行求)
print(df.sum(axis=1))    # 12  15  18
print(df.mean(axis=1))   # 4.0 5.0 6.0
记忆技巧:axis=0 是"沿着行方向移动"→ 对每一列计算;axis=1 是"沿着列方向移动"→ 对每一行计算。很多新手在这里混淆,请务必亲手跑一遍。

8.3 DataFrame 与 Series 运算(广播)

# 每列都减去该列的均值(自动按列对齐)
df2 = df - df.mean()

# 每行都除以该行的和(需要配合 axis 参数)
df3 = df.div(df.sum(axis=1), axis=0)

9. 转置与轴向操作

# 转置:行列互换
print(df.T)

# 沿着轴堆叠
df_a = pd.DataFrame({"x": [1, 2]})
df_b = pd.DataFrame({"x": [3, 4]})

# 纵向拼接(axis=0,默认):行数增加
pd.concat([df_a, df_b], axis=0)

# 横向拼接(axis=1):列数增加
pd.concat([df_a, df_b], axis=1)

(合并的完整知识见第 11 章)


10. 常见坑与注意事项

| 坑 | 现象 | 解决办法 |

|----|------|----------|

| 链式赋值警告 | df[df.x>1]["y"]=5 报 SettingWithCopyWarning | 改用 .loc 一次性操作 |

| axis 记反 | 统计结果与预期相反 | 记住 axis=0 按列、axis=1 按行 |

| drop 忘赋值 | 删除后原表没变 | df = df.drop(...) 或 inplace=True |

| 混用 df.列名 与 df["列名"] | 列名含空格/中文/特殊字符时 df.列名 报错 | 统一用 df["列名"] |

| 误以为 df["a","b"] 可取两列 | 报 KeyError | 必须写成 df[["a","b"]] |


11. 本章小结与练习

小结

  • DataFrame 是二维表格,由 index + columns + values 组成;
  • 常用创建方式:字典、列表的列表、ndarray、记录列表、文件读取;
  • 核心属性:shape、dtypes、index、columns、values;
  • 增删改:新增列直接赋值、drop 删行列、.at/.loc 改值、rename 改名;
  • axis=0 按列、axis=1 按行,这是最容易出错也最重要的概念之一。

练习题

1. 用字典创建包含 4 名学生(姓名、语文、数学、英语)的 DataFrame。

2. 新增一列"总分"= 三门成绩之和,再新增一列"平均分"。

3. 打印出所有学生的平均分均值、总分最大值。

4. 删除"平均分"列,重命名"语文"为"chinese"。

5. 使用 .loc 将分数低于 60 的单元格改为 60。


下一篇预告:第 4 章 数据读取与写入 —— 从 CSV、Excel、JSON、SQL 等常见格式读写数据。
— 全文完 —回到顶部 ↑
下载推广海报

文章推广海报

《第 3 章 DataFrame 详解》完整推广海报
DISCUSSION

文章回复

0 条公开回复
未登录回复需要审核后公开
还没有回复,欢迎参与讨论。