3.1 Series 与 DataFrame 数据结构


3.1 Series 与 DataFrame 数据结构

本节摘要:Series 是带标签的一维数组,DataFrame 是由多个 Series 组成的二维表格——Pandas 的一切操作都建立在这两个结构上。本节讲清它们的组织方式、索引(index)的核心作用,以及最常用的创建与属性操作。

本节导航

阅读完本节,你应当能够:

  1. 说清 Series 与 DataFrame 的区别和联系
  2. 从列表、字典、NumPy 数组创建 Series 与 DataFrame
  3. 理解 index 与 columns 的作用,会用它们定位数据
  4. 使用 shape、dtypes、values 等常用属性
  5. 判断何时该用 Series、何时该用 DataFrame

一、问题与直觉

上一章的 NumPy 数组很强大,但它有个短板:没有名字。数组里的第 3 个元素到底是"北京店的销售额"还是"上海店的销售额",NumPy 不知道。真实数据几乎都带着语义——列名、行名、日期标签。Pandas 就是给 NumPy 数组"贴上标签"的库:一维带标签的叫 Series,二维带标签的叫 DataFrame。

这就好比 NumPy 是仓库里码好的货物,Pandas 是给每件货贴上名称和编号的货架系统。有了标签,你才能说"取北京店的数据"而不是"取第 3 行的数据"。

二、核心原理

2.1 Series:一维带标签数组

先看两个结构的关系,再逐个展开:

索引是 Series 的灵魂——有了它,s2["上海"] 就能直接取出 15,而不是靠位置猜。

2.2 DataFrame:二维带标签表格

DataFrame 可以看作"多个 Series 并排拼成的表":每一列是一个 Series,所有列共享同一个行索引;每一行是一条记录。它同时有行索引(index)和列名(columns)两套标签。

# 从字典创建,键是列名 df = pd.DataFrame({ "门店": ["北京", "上海", "广州"], "销售额": [12, 15, 9], "客单价": [299, 355, 410], })

2.3 两种数据结构的关系

2.3 两种数据结构的关系

df["销售额"] 取出一列,返回的正是 Series。反过来,把多个 Series 用字典装起来就能拼成 DataFrame。这个"列即 Series"的关系是理解 Pandas 一切操作的钥匙。

三、工程实践要点

3.1 常用属性速查

df.shape # 行数、列数,如 (3, 3) df.index # 行索引 df.columns # 列名 df.dtypes # 每列的类型 df.values # 转成 NumPy 数组 df.head() # 前 5 行 df.info() # 类型 + 非空计数 df.describe() # 数值列统计摘要

3.2 创建 DataFrame 的几种姿势

# 方式一:字典(键为列名,值为列表) df1 = pd.DataFrame({"a": [1, 2], "b": [3, 4]}) # 方式二:列表套字典(每行一个字典) df2 = pd.DataFrame([{"a": 1, "b": 3}, {"a": 2, "b": 4}]) # 方式三:从 NumPy 数组 + 指定列名 import numpy as np df3 = pd.DataFrame(np.random.rand(3, 2), columns=["x", "y"]) # 方式四:指定行索引 df4 = pd.DataFrame(data, index=["一月", "二月", "三月"])

3.3 选择 Series 还是 DataFrame

场景 用哪个 原因
单独一列数据 Series 轻量、够用
多列关联数据 DataFrame 结构完整
中间计算结果(如均值序列) Series groupby 聚合结果
建模输入 DataFrame 特征矩阵形式

💡 关键直觉:看到"一维数据 + 标签"就想到 Series,看到"表格"就想到 DataFrame。转换也很简单:df["列名"] 得 Series,s.to_frame() 回 DataFrame。

3.4 贯穿案例:创建门店订单 DataFrame

import pandas as pd df_orders = pd.DataFrame({ "订单号": ["A001", "A002", "A003", "A004"], "门店": ["北京", "上海", "北京", "广州"], "金额": [199, 355, 89, 1299], "日期": ["2026-01-01", "2026-01-01", "2026-01-02", "2026-01-02"], }) print(df_orders) print("表格形状:", df_orders.shape) print("金额列均值:", df_orders["金额"].mean())

这张表就是贯穿全书案例的雏形,下一节我们学怎么把它加载得更真实、筛选得更灵活。

3.5 索引的进阶操作

索引不只是"标签",还承担着定位与对齐的职责:

df = pd.DataFrame({"金额": [199, 355, 89]}, index=["A001", "A002", "A003"]) df.index # 查看索引 df.reset_index() # 索引变回普通列 df.set_index("订单号") # 指定列变索引 df.sort_index() # 按索引排序 df.loc["A001"] # 按索引取行

💡 关键直觉:set_indexreset_index 是一对互逆操作。分组聚合后索引通常是分组键,用 reset_index() 把它还原成普通列,是"分组结果继续参与运算"的必备动作,第 3.4 节还会见到。

3.6 Series 的算术与对齐

Series 之间运算时,按索引对齐而不是按位置:

s1 = pd.Series({"北京": 12, "上海": 15}) s2 = pd.Series({"上海": 10, "北京": 8}) print(s1 + s2) # 北京 20,上海 25——按标签对齐相加

这个特性让"两个来源的数据按名称合并"变得自然:不需要关心顺序,标签相同就自动对上。对齐不到的标签结果是 NaN,这也是合并后常见缺失的来源。

3.7 常用属性与转换速查

需求 代码
行列数 df.shape
列名列表 df.columns.tolist()
行索引 df.index
每列类型 df.dtypes
转 NumPy df.valuesdf.to_numpy()
转字典 df.to_dict()
取单列成 Series df["列名"]
Series 转回表 s.to_frame()

to_numpy() 是 Pandas 与 NumPy 互通的桥——把 DataFrame 交给算法库时,通常要先转成数组。

⚠️ 常见坑:df["列名"] 取单列返回的是 Series 而不是 DataFrame——它没有 columns 属性,df["列名"].columns 会报错。需要保持表结构时用双括号 df[["列名"]]。这个差别在链式操作里最容易踩。

一节小结

  • 要点一:Series 是一维带标签数组,索引是它的灵魂,按标签取值而非按位置猜
  • 要点二:DataFrame 是二维表,行有 index、列有 columns,每列本质是一个 Series
  • 要点三df[列名] 返回 Series,s.to_frame() 变回 DataFrame,两者随时互转
  • 要点四:创建四姿势——字典、列表套字典、NumPy 数组、指定 index
  • 要点五:探查四件套——head、info、describe、shape,拿到表先跑一遍
  • 要点六df.values 转 NumPy 数组,是 Pandas 与 NumPy 的桥

结构认识了,接下来让数据真正"进来"——下一节讲数据加载与索引筛选,掌握 loc、iloc 和布尔索引三种取数姿势。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U