首页 / Pandas 入门教程 / Series:一维数据结构

Pandas 入门教程

Series:一维数据结构

本教程共 54 篇 · 第 5 篇 · 更新于 2026-08-11 · 约 8 分钟阅读

PandasPandas 入门教程Series一维数组索引数据对齐

本节目标:掌握 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"] = 99s.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。