Pandas中Series序列的具体实现
作者:林深时见鹿1
一、Series 的核心定义
Series 是 Pandas 专为一维数据设计的结构,对比 NumPy 一维数组,核心差异是:
表格
| 特性 | Pandas Series | NumPy 一维数组 |
|---|---|---|
| 索引 | 支持自定义标签(字符串 / 数字 / 时间等) | 仅支持整数位置索引 |
| 数据类型 | 可混合类型(如同时存 int/str) | 仅支持同一种数据类型 |
| 缺失值 | 原生支持 NaN,内置缺失值处理方法 | 需手动处理 NaN |
| 功能 | 内置统计 / 对齐 / 可视化等方法 | 仅基础数值计算 |
直观理解:把 Series 想象成 “带列名的一列数据”,由两部分组成:
- values:数据本身(底层是 NumPy 数组);
- index:自定义标签(索引),和数据一一对应。
二、创建 Series(核心语法)
创建 Series 的核心函数是 pd.Series(),最常用的 4 种方式如下:
1. 从列表 / 数组创建(基础)
import pandas as pd
import numpy as np
# 方式1:从列表创建(默认整数索引 0,1,2...)
scores = [85, 92, 78, 90, 88]
s1 = pd.Series(scores)
print("从列表创建的Series:")
print(s1)
# 方式2:指定自定义索引
names = ["小明", "小红", "小刚", "小丽", "小强"]
s2 = pd.Series(scores, index=names)
print("\n指定索引的Series:")
print(s2)
# 方式3:从NumPy数组创建
arr = np.array([15.2, 16.1, 14.8, 15.5])
s3 = pd.Series(arr, index=["1月", "2月", "3月", "4月"], name="月均温度")
print("\n带名称的Series:")
print(s3)输出:
从列表创建的Series:
0 85
1 92
2 78
3 90
4 88
dtype: int64
指定索引的Series:
小明 85
小红 92
小刚 78
小丽 90
小强 88
dtype: int64
带名称的Series:
1月 15.2
2月 16.1
3月 14.8
4月 15.5
Name: 月均温度, dtype: float64
2. 从字典创建(索引 = 字典 key,值 = 字典 value)
import pandas as pd
# 字典:键=姓名,值=分数
score_dict = {"小明":85, "小红":92, "小刚":78, "小丽":90}
s4 = pd.Series(score_dict)
print("从字典创建的Series:")
print(s4)输出:
从字典创建的Series:
小明 85
小红 92
小刚 78
小丽 90
dtype: int64
3. 创建含缺失值的 Series
import pandas as pd
import numpy as np
# 含NaN的Series(缺失值)
s5 = pd.Series([85, np.nan, 92, 78, np.nan], index=["小明", "小红", "小刚", "小丽", "小强"])
print("含缺失值的Series:")
print(s5)输出:
含缺失值的Series:
小明 85.0
小红 NaN
小刚 92.0
小丽 78.0
小强 NaN
dtype: float64
三、Series 的核心操作(索引 / 切片)
Series 支持两种索引方式:标签索引(自定义 index)和位置索引(整数位置),这是和 NumPy 数组的核心区别。
1. 标签索引(最常用)
通过自定义索引取值 / 赋值:
import pandas as pd
s = pd.Series([85, 92, 78, 90], index=["小明", "小红", "小刚", "小丽"])
# 取值:通过标签
print("小红的分数:", s["小红"]) # 92
# 赋值:通过标签
s["小刚"] = 80
print("\n修改小刚分数后:")
print(s)
# 多标签取值(返回新Series)
print("\n小明和小丽的分数:")
print(s[["小明", "小丽"]])输出:
小红的分数: 92
修改小刚分数后:
小明 85
小红 92
小刚 80
小丽 90
dtype: int64
小明和小丽的分数:
小明 85
小丽 90
dtype: int64
2. 位置索引(和 NumPy 一致)
通过整数位置(0 开始)取值,可用 iloc 明确指定位置索引(推荐,避免歧义):
import pandas as pd
s = pd.Series([85, 92, 78, 90], index=["小明", "小红", "小刚", "小丽"])
# 直接用整数(简易写法)
print("第2个元素(位置1):", s[1]) # 92
# 用iloc(明确位置索引,推荐)
print("第4个元素(位置3):", s.iloc[3]) # 90
# 位置切片
print("\n位置0-2的元素:")
print(s.iloc[0:3])输出:
第2个元素(位置1): 92
第4个元素(位置3): 90
位置0-2的元素:
小明 85
小红 92
小刚 78
dtype: int64
3. 布尔索引(筛选数据)
和 NumPy 类似,通过布尔条件筛选元素:
import pandas as pd
s = pd.Series([85, 92, 78, 90, 88], index=["小明", "小红", "小刚", "小丽", "小强"])
# 筛选分数≥90的元素
high_score = s[s >= 90]
print("90分以上的学生:")
print(high_score)
# 筛选分数在80-90之间的元素
mid_score = s[(s >= 80) & (s < 90)]
print("\n80-90分的学生:")
print(mid_score)输出:
90分以上的学生:
小红 92
小丽 90
dtype: int64
80-90分的学生:
小明 85
小强 88
dtype: int64
四、Series 的核心属性与方法
1. 核心属性(快速查看数据特征)
表格
| 属性 | 作用 | 示例 |
|---|---|---|
| values | 返回底层 NumPy 数组 | s.values → array([85,92,78,90]) |
| index | 返回索引对象 | s.index → Index ([' 小明 ',' 小红 ',' 小刚 ',' 小丽 '], dtype='object') |
| dtype | 返回数据类型 | s.dtype → int64 |
| shape | 返回形状(一维元组) | s.shape → (4,) |
| name | 返回 Series 名称 | s.name → ' 分数' |
| isnull() | 返回布尔 Series(NaN 为 True) | s.isnull() → 小红:True, 小强:True |
| notnull() | 返回布尔 Series(非 NaN 为 True) | s.notnull() → 小明:True, 小红:False |
运行
import pandas as pd
import numpy as np
s = pd.Series([85, np.nan, 92, 78], index=["小明", "小红", "小刚", "小丽"], name="分数")
print("底层数组:", s.values)
print("索引:", s.index)
print("数据类型:", s.dtype)
print("形状:", s.shape)
print("名称:", s.name)
print("缺失值判断:")
print(s.isnull())输出:
底层数组: [85. nan 92. 78.]
索引: Index(['小明', '小红', '小刚', '小丽'], dtype='object')
数据类型: float64
形状: (4,)
名称: 分数
缺失值判断:
小明 False
小红 True
小刚 False
小丽 False
dtype: bool
2. 常用方法(统计 / 缺失值 / 排序)
(1)统计方法(和 NumPy 类似,但更友好)
import pandas as pd
import numpy as np
s = pd.Series([85, np.nan, 92, 78, 90], index=["小明", "小红", "小刚", "小丽", "小强"])
# 基础统计
print("均值(自动忽略NaN):", s.mean()) # 86.25
print("中位数:", s.median()) # 87.5
print("最大值/最小值:", s.max(), "/", s.min()) # 92 / 78
print("标准差:", s.std()) # 6.18...
# 描述性统计(一键生成)
print("\n描述性统计:")
print(s.describe())输出:
均值(自动忽略NaN): 86.25
中位数: 87.5
最大值/最小值: 92.0 / 78.0
标准差: 6.18465843842649
描述性统计:
count 4.000000
mean 86.250000
std 6.184658
min 78.000000
25% 83.250000
50% 87.500000
75% 90.500000
max 92.000000
dtype: float64
(2)缺失值处理
import pandas as pd
import numpy as np
s = pd.Series([85, np.nan, 92, 78, np.nan], index=["小明", "小红", "小刚", "小丽", "小强"])
# 1. 删除缺失值
s_drop = s.dropna()
print("删除缺失值后:")
print(s_drop)
# 2. 填充缺失值(均值/中位数/固定值)
s_fill_mean = s.fillna(s.mean()) # 均值填充
s_fill_0 = s.fillna(0) # 固定值填充
print("\n均值填充缺失值:")
print(s_fill_mean)输出:
删除缺失值后:
小明 85.0
小刚 92.0
小丽 78.0
dtype: float64
均值填充缺失值:
小明 85.0
小红 85.0
小刚 92.0
小丽 78.0
小强 85.0
dtype: float64
(3)排序
import pandas as pd
s = pd.Series([85, 92, 78, 90], index=["小明", "小红", "小刚", "小丽"])
# 按值升序排序
s_sort_val = s.sort_values()
print("按分数升序:")
print(s_sort_val)
# 按索引降序排序
s_sort_idx = s.sort_index(ascending=False)
print("\n按姓名降序:")
print(s_sort_idx)输出:
按分数升序:
小刚 78
小明 85
小丽 90
小红 92
dtype: int64
按姓名降序:
小丽 90
小红 92
小明 85
小刚 78
dtype: int64
(4)值替换 / 映射
import pandas as pd
s = pd.Series([85, 92, 78, 59, 90], index=["小明", "小红", "小刚", "小亮", "小丽"])
# 替换单个值(不及格→60)
s_replace = s.replace(59, 60)
print("替换不及格分数后:")
print(s_replace)
# 映射(分数→等级)
grade_map = {x: "优秀" if x>=90 else "良好" if x>=80 else "及格" for x in s}
s_grade = s.map(grade_map)
print("\n分数映射为等级:")
print(s_grade)输出:
替换不及格分数后:
小明 85
小红 92
小刚 78
小亮 60
小丽 90
dtype: int64
分数映射为等级:
小明 良好
小红 优秀
小刚 及格
小亮 及格
小丽 优秀
dtype: object
五、Series 与 NumPy 数组 / 列表的转换
实际开发中常需要在不同结构间转换:
import pandas as pd
import numpy as np
# 1. Series → NumPy数组
s = pd.Series([85, 92, 78, 90], index=["小明", "小红", "小刚", "小丽"])
arr = s.values
print("Series转数组:", arr) # [85 92 78 90]
# 2. Series → 列表
lst = s.tolist()
print("Series转列表:", lst) # [85, 92, 78, 90]
# 3. NumPy数组 → Series
arr2 = np.array([15.2, 16.1, 14.8])
s2 = pd.Series(arr2, index=["1月", "2月", "3月"])
print("\n数组转Series:")
print(s2)
# 4. 列表 → Series
lst2 = [88, 76, 95]
s3 = pd.Series(lst2, index=["小强", "小芳", "小伟"])
print("\n列表转Series:")
print(s3)六、实战场景:Series 的典型应用
场景 1:时间序列数据处理
import pandas as pd
import numpy as np
# 创建日期索引的Series(7天温度)
dates = pd.date_range(start="2026-01-01", periods=7)
temp = pd.Series(np.random.normal(5, 3, 7).round(1), index=dates, name="日温")
# 查看数据
print("7天温度数据:")
print(temp)
# 筛选1月3日之后的温度
print("\n1月3日之后的温度:")
print(temp[temp.index >= "2026-01-03"])
# 计算周平均温度
print("\n周平均温度:", temp.mean())场景 2:数据清洗(缺失值填充)
import pandas as pd
import numpy as np
# 模拟学生分数(含缺失值)
scores = pd.Series([85, np.nan, 92, 78, np.nan, 88, 95],
index=["小明", "小红", "小刚", "小丽", "小强", "小芳", "小伟"])
# 步骤1:统计缺失值数量
nan_count = scores.isnull().sum()
print("缺失值数量:", nan_count)
# 步骤2:用中位数填充缺失值
scores_filled = scores.fillna(scores.median())
print("\n填充后的分数:")
print(scores_filled)
# 步骤3:筛选优秀学生(≥90)
excellent = scores_filled[scores_filled >= 90]
print("\n优秀学生:")
print(excellent)七、避坑点与最佳实践
1. 核心避坑点
- ❌ 混淆标签索引和位置索引:当索引是整数时(如 index=[1,2,3]),s[1] 会优先按标签取值,而非位置,建议用 iloc 明确位置索引;
- ❌ 忽略缺失值:Series 的统计方法(如 mean())会自动忽略 NaN,但如果需要包含 NaN 需手动处理;
- ❌ 直接修改 Series 索引:index 是不可变对象,需用 s.reset_index() 或 s.set_index() 修改;
- ❌ 布尔条件组合错误:多条件组合需用 &/|(而非 and/or),且每个条件需用括号包裹。
2. 最佳实践
- ✅ 索引命名:创建 Series 时给 index 和 name 命名,增强可读性;
- ✅ 明确索引方式:位置索引用 iloc,标签索引用 loc(s.loc["小红"]),避免歧义;
- ✅ 缺失值处理:先统计缺失值数量(isnull().sum()),再选择填充 / 删除策略;
- ✅ 大数据处理:Series 底层是 NumPy 数组,优先用向量化方法(如 map/apply),避免循环。
总结
- Series 是 Pandas 一维带标签的数据结构,由 values(数据)和 index(标签)组成,支持混合数据类型和缺失值;
- 核心操作:
- 索引:标签索引(s["小红"]/s.loc["小红"])、位置索引(s.iloc[1]);
- 筛选:布尔索引(s[s>=90]);
- 统计:mean()/median()/std()(自动忽略 NaN);
- 缺失值:dropna()/fillna();
- 核心优势:对比 NumPy 数组,Series 支持自定义标签、缺失值原生处理、丰富的统计 / 清洗方法;
- 避坑关键:明确索引方式,处理缺失值,正确组合布尔条件。
到此这篇关于Pandas中Series序列的具体实现的文章就介绍到这了,更多相关Pandas Series序列内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
