Series:一维数据结构
本教程共 54 篇 · 第 5 篇 · 更新于 2026-08-11 · 约 8 分钟阅读
本节目标:掌握 Series 的创建方式、索引和切片、常用属性与运算,弄懂它和 NumPy 数组的异同。
Series 是什么
Series 是一维带标签数组,由两部分组成:数据和索引。索引可以不连续、不从 0 开始,可以是字符串、日期等任意标签。
官方定义:一维同质类型数组,能装整数、浮点、字符串、Python 对象等任何类型。
Series 有两种看待方式:
- 像带标签的 NumPy 数组:支持向量化运算、切片
- 像固定大小的字典:按标签取值、判断键是否存在
Series 与 NumPy 数组
Series 和 ndarray 最大的区别有三个:
- Series 有索引,ndarray 只有位置
- 运算时 Series 按标签对齐,ndarray 按位置
- Series 显示时带着索引一起打印,ndarray 只有数字
其余行为高度相似:向量化、切片、传给 NumPy 函数都可以。
这也是为什么 pandas 强调「标签」而非「下标」:数据分析里,行名通常比行号有意义。
创建 Series
从列表创建:
import numpy as np
import pandas as pd
# 不传 index 时自动生成 0 开头的整数索引
s = pd.Series([10, 20, 30])
print(s)
从字典创建最符合直觉:键是标签,值是数据。注意 pandas 会保留字典的顺序,索引按插入顺序排列。
从字典创建,键变索引:
import pandas as pd
# 字典的键成为索引,值成为数据
s2 = pd.Series({"苹果": 3, "香蕉": 5, "橙子": 2})
print(s2)
从 ndarray 创建:
import numpy as np
import pandas as pd
# 数组加自定义索引,两者长度必须一致
arr = np.array([1.0, 2.5, 3.0])
s3 = pd.Series(arr, index=["a", "b", "c"])
print(s3)
从标量创建,自动广播:
import pandas as pd
# 标量会重复填满整个索引
s4 = pd.Series(5.0, index=["a", "b", "c"])
print(s4)
从 DataFrame 取列
Series 最常见的来源其实是 DataFrame 的一列:取出来自动带上列名当 name。
import pandas as pd
df = pd.DataFrame({"苹果": [1, 2, 3], "香蕉": [4, 5, 6]})
col = df["苹果"]
print(type(col)) # pandas Series
print(col.name) # 苹果
反过来,多个 Series 也可以拼回 DataFrame(§06 细讲)。一列一表来回切换,是 pandas 的日常。
索引与取值
Series 可以像字典一样按标签取值:
import pandas as pd
s = pd.Series({"苹果": 3, "香蕉": 5, "橙子": 2})
print(s["苹果"]) # 按标签取,3
print("香蕉" in s) # True,判断标签是否存在
print(s.get("梨", 0)) # 安全取值:不存在返回默认值 0
标签不存在时,s["梨"] 会抛 KeyError;用 get 可以优雅兜底。
索引允许重复。万一出现重复标签,按标签取值会返回一个 Series 而不是标量,写代码时留意:
import pandas as pd
s = pd.Series([1, 2], index=["a", "a"])
print(s["a"]) # 返回 Series,不是单个值
按位置取值用 iloc,也支持列表和切片:
import pandas as pd
s = pd.Series([10, 20, 30, 40], index=["a", "b", "c", "d"])
print(s.iloc[0]) # 第 0 个位置:10
print(s.iloc[[0, 2]]) # 按位置列表取
print(s.loc[["a", "c"]]) # 按标签列表取
loc 和 iloc 都能接受列表、切片、条件,是 pandas 选择数据的主力,§19 会系统讲。
pandas 3.0 起,s[0] 这种整数下标一律按「标签」解释(和 DataFrame 一致),不再按位置。按位置取值请显式写 s.iloc[0],语义清晰还不踩坑。
常用属性
import pandas as pd
s = pd.Series([10, 20, 30], index=["a", "b", "c"], name="销量")
print(s.dtype) # int64
print(s.index) # Index(['a', 'b', 'c'], dtype='str')
print(s.name) # 销量
print(s.to_numpy()) # 转成 NumPy 数组 [10 20 30]
s.array 可以拿到底层扩展数组,一般用不到,知道存在即可,比如需要绕过 pandas 对齐逻辑时。
name 是 Series 的名字,从 DataFrame 取列时会自动带上列名,改名用 rename:
import pandas as pd
s = pd.Series([10, 20, 30], name="销量")
print(s.rename("新名字").name)
索引对象本身不可修改,想要新的索引就重新构造或用 reindex(后面章节会讲)。
遍历 Series
直接 for 循环遍历的是值:
import pandas as pd
s = pd.Series([10, 20, 30], index=["a", "b", "c"])
for v in s:
print(v) # 10 20 30
想同时拿标签和值,用 items():
import pandas as pd
s = pd.Series([10, 20, 30], index=["a", "b", "c"])
for label, value in s.items():
print(label, value) # a 10 / b 20 / c 30
老版本的
已经移除,遍历请用
items()。日常数据处理更推荐向量化写法,循环只用于少量场景。
多数场景下,向量化写法既快又短,比如 s * 2 比 for 循环逐个拼接高效得多。
切片
切片和 Python 类似,但分两种写法:
import pandas as pd
s = pd.Series([10, 20, 30, 40, 50], index=list("abcde"))
# 按位置切片:左闭右开,和 Python 一样
print(s.iloc[1:3])
# 按标签切片:两端都包含
print(s.loc["b":"d"])
# 布尔筛选
print(s[s > 25])
注意标签切片和位置切片的最大区别:标签切片是闭区间,包含两端。
切片得到的还是 Series,可以继续链式操作,比如 s.iloc[1:3].mean()。
Series 也有 head/tail,预览数据时常用:
import pandas as pd
s = pd.Series(range(100))
print(s.head()) # 前 5 个
print(s.tail(2)) # 最后 2 个
常用的统计方法
Series 自带一批统计方法,直接调用即可:
import pandas as pd
s = pd.Series([1, 2, 3, 4, 100])
print(s.sum()) # 110
print(s.mean()) # 22.0
print(s.max()) # 100
print(s.min()) # 1
print(s.count()) # 5,非缺失值的个数
count() 数非缺失值,想知道缺失几个用 isna().sum()。布尔 Series 也可以直接 sum(),结果就是 True 的个数。
想知道每个值出现几次,用 value_counts():它返回一个 Series,索引是原始值,数据是次数。统计方法的完整清单在 §18。
运算与对齐
Series 支持向量化运算,不用写循环:
import numpy as np
import pandas as pd
s = pd.Series([1, 2, 3], index=["a", "b", "c"])
print(s * 2) # 每个元素乘 2
print(s + s) # 对应元素相加
print(np.exp(s)) # NumPy 函数直接可用
# 比较运算得到布尔 Series,可以用来筛选
print(s > 2)
更妙的是自动对齐:两个索引不同的 Series 做运算,pandas 会按标签配对,对不上的位置填 NaN,和顺序无关。完整的机制和示例在 §08 详讲,这里记住”按标签配对、缺标签得 NaN”就够了。聚合运算默认跳过缺失值,比如 s1.mean() 不会因为 NaN 出错。
修改 Series 里的元素也简单:s.loc["b"] = 99 或 s.iloc[0] = 99。在 CoW 下(第 04 章讲过),修改只影响这个 Series 自己,不会波及其他对象。
四种创建方式怎么选?数据在手就用列表或 ndarray;数据天然是键值对就用字典;要造默认值序列用标量。多数情况列表和字典够用。多数情况列表和字典够用,按手头数据的形态选最省事的就行。
缺失值的基础处理
Series 带 NaN 是常态,几个基础动作先认识:
import pandas as pd
s = pd.Series([1, 2, None, 4])
print(s.isna()) # 哪些位置缺失:False False True False
print(s.dropna()) # 丢掉缺失:1, 2, 4
print(s.fillna(0)) # 缺失填 0
判断缺失统一用 isna(),不要直接和 None 或 np.nan 比较。缺失值的完整处理在第 24、25 章。
小结
动手练一下:从字典创建一个 Series(比如城市人口),试试按标签取值、get 兜底、iloc 切片、s * 2 运算,再把两个不同索引的 Series 相加,观察 NaN 出现的位置。
Series 等于数据加索引加名字。创建有四种姿势(列表、字典、ndarray、标量),取值分清按标签和按位置,运算自动对齐。下一章看它的「老大」DataFrame。