查看全课大纲(第 34 / 101 节)
  1. 1.数据分析基本概念
  2. 2.学习数据分析的一般路线
  3. 3.数据分析的流程
  4. 4.数据类型
  5. 5.环境部署(1)
  6. 6.环境部署(2)
  7. 7.课程介绍
  8. 8.TXT文件操作
  9. 9.JSON文件操作
  10. 10.CSV文件操作
  11. 11.Excel文件操作
  12. 12.数据库及SQL常用语法
  13. 13.数据库基本操作
  14. 14.数据库多表连接
  15. 15.实战:欧洲职业足球数据库分析
  16. 16.爬虫简介
  17. 17.URL管理模块
  18. 18.网页下载模块
  19. 19.网页解析模块(1)
  20. 20.网页解析模块(2)
  21. 21.Scrapy简介
  22. 22.Scrapy使用步骤(1)
  23. 23.Scrapy使用步骤(2)
  24. 24.Scrapy使用步骤(3)
  25. 25.Scrapy使用步骤(4)
  26. 26.实战:获取国内城市空气质量指数数据
  27. 27.NumPy和SciPy介绍
  28. 28.多维数组
  29. 29.多维数组操作
  30. 30.NumPy的常用方法
  31. 31.向量化介绍
  32. 32.向量化及通用函数
  33. 33.实战:2016美国大选分析
  34. 34.数据结构-Series
  35. 35.数据结构-DataFrame
  36. 36.数据结构-Index
  37. 37.Series的索引操作
  38. 38.DataFrame的索引操作
  39. 39.索引操作总结
  40. 40.运算与对齐
  41. 41.函数应用操作(1) -- map
  42. 42.函数应用操作 (2) -- apply applymap
  43. 43.文件读写操作
  44. 44.排序操作
  45. 45.数据清洗--处理缺失数据
  46. 46.数据清洗--处理重复数据
  47. 47.数据清洗--替换数据
  48. 48.常用统计方法(1) -- describe quantile
  49. 49.常用统计方法(2) -- sum mean median count
  50. 50.常用统计方法(3) -- max min idxmax idxmin
  51. 51.常用统计方法(4) -- mad var std cumsum
  52. 52.实战:全球食品数据分析
  53. 53.层级索引
  54. 54.分组与聚合介绍
  55. 55.分组操作(1) -- GroupBy对象及常用聚合操作
  56. 56.分组操作(2) -- 自定义分组及聚合操作
  57. 57.透视表介绍
  58. 58.透视表操作
  59. 59.数据规整(1) -- 数据合并concat
  60. 60.数据规整(2) -- 数据连接merge
  61. 61.数据重构(3) -- 数据重构stack unstack
  62. 62.实战:互联网电影资料库分析
  63. 63.探索性数据分析EDA介绍
  64. 64.EDA的目的
  65. 65.EDA常用工具
  66. 66.Matplotlib绘图基本介绍
  67. 67.Matplotlib画布
  68. 68.散点图和柱状图的绘制
  69. 69.直方图的绘制
  70. 70.矩阵绘图
  71. 71.子图的使用
  72. 72.Matplotlib颜色、标记、线型
  73. 73.Matplotlib坐标刻度、标签、图例、标题
  74. 74.Seaborn介绍
  75. 75.数据集分布可视化(1) -- 单变量分布、双变量分布
  76. 76.数据集分布可视化(2) -- 变量关系可视化
  77. 77.类别数据可视化 -- 类别散布图、类别内数据分布、类别内统计图
  78. 78.交互式数据可视化工具Bokeh介绍
  79. 79.Bokeh绘制散点图、柱状图、盒子图、弦图
  80. 80.Bokeh绘制常用图形元素
  81. 81.3D绘图 -- mplot3d
  82. 82.3D曲线可视化
  83. 83.3D散点图可视化
  84. 84.3D柱状图可视化
  85. 85.Pandas绘图
  86. 86.实战:Lending Club借贷数据探索性分析及可视化
  87. 87.机器学习介绍及应用场景
  88. 88.机器学习建模介绍 (1) -- 分类
  89. 89.机器学习建模介绍 (2) -- 回归
  90. 90.机器学习建模介绍 (3) -- 聚类
  91. 91.机器学习分类
  92. 92.机器学习工具scikit-learn
  93. 93.使用scikit-learn的流程
  94. 94.数据集准备及划分
  95. 95.模型选择
  96. 96.数据预处理及特征工程
  97. 97.过拟合与欠拟合
  98. 98.模型调参介绍
  99. 99.模型调参方法
  100. 100.模型测试及评价
  101. 101.实战:通过移动设备行为数据预测性别和年龄

数据结构-Series

约 18 分钟

📺 正在播放小象学院官方高清录播(支持倍速与清晰度调节)

Series:Pandas 的一维数据结构

小象实战讲义 · Python数据分析实战

在掌握了NumPy的多维数组操作后,我们将正式进入数据分析的核心工具——Pandas的学习。Pandas是专为处理结构化数据而设计的强大工具集,它构建在NumPy之上,提供了更高级的数据抽象和便捷的操作方法。本节将首先学习Pandas中最基础、最重要的数据结构之一:Series。理解Series是后续学习DataFrame和进行复杂数据分析的基石。

💡 核心导读

  • 认识Pandas:了解Pandas的起源(金融数据分析工具)及其基于NumPy的高性能特性。
  • Series的本质:将Series理解为一维带标签的数组,掌握其核心三要素:数据(values)、索引(index)和名称(name)。
  • Series的创建:学会通过列表、NumPy数组、字典等多种方式创建Series对象。
  • 数据的访问与预览:使用.head()、.tail()预览数据,并通过标签(.loc)或位置(.iloc)精确访问数据。
  • 缺失值处理:了解Pandas如何根据数据类型自动处理缺失数据(如None、NaN)。

什么是Pandas?

Pandas是一个强大的Python数据分析库,专门用于处理和分析结构化数据(例如表格数据)。它最初于2008年被创建,主要目的是作为金融数据分析的工具。正因为金融数据通常具有时间序列、高维度和大量缺失值等特点,处理起来非常复杂,所以Pandas在设计之初就具备了强大的数据处理能力。如今,它已广泛应用于各个领域的数据分析任务。

Pandas的核心基础是NumPy。这意味着NumPy支持的所有高性能矩阵运算,在Pandas中同样可用。但Pandas在NumPy数组的基础上,增加了数据标签(索引)、列名以及大量方便数据清洗、转换和分析的方法,使得处理表格数据变得异常高效和直观。

Series:带标签的一维数组

Series是Pandas中最基本的数据结构。你可以将它看作一个一维的、带有标签的数组。这里的“标签”就是索引(index),它使得我们能够通过有意义的标签(而不仅仅是数字位置)来访问数据。

一个Series对象主要由三部分组成:

  1. 数据(values):实际存储的数据。数值型数据的底层是 NumPy 的 ndarray;字符串等类型在新版 pandas 中使用专门的扩展数组(如本节练习中将见到的 StringArray)。
  2. 索引(index):与数据一一对应的标签。如果没有显式指定,Pandas会自动生成从0开始的整数索引。
  3. 名称(name):整个Series可以有一个名字,索引也可以有自己的名字,这有助于更好地描述数据。

创建Series

Series可以通过多种方式创建,每种方式都体现了其灵活性。

import pandas as pd
import numpy as np

# 1. 通过列表创建
# 未指定索引时,自动生成0,1,2,...的整数索引
series_from_list = pd.Series([10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
print("通过列表创建的Series:")
print(series_from_list)
print()
通过列表创建的Series:
0    10
1    11
2    12
3    13
4    14
5    15
6    16
7    17
8    18
9    19
dtype: int64
import pandas as pd
import numpy as np

# 2. 通过NumPy数组创建
arr = np.array([0.1, 0.2, 0.3, 0.4])
series_from_ndarray = pd.Series(arr)
print("通过NumPy数组创建的Series:")
print(series_from_ndarray)
print()

# 3. 通过字典创建
# 字典的键(key)会自动成为Series的索引,值(value)成为数据
dict_data = {'北京': 2154, '上海': 2428, '广州': 1490, '深圳': 1303}
series_from_dict = pd.Series(dict_data)
print("通过字典创建的Series:")
print(series_from_dict)
print()

# 4. 创建时显式指定索引
# 数据与索引列表必须长度一致
data = [88, 92, 79, 85]
custom_index = ['语文', '数学', '英语', '物理']
series_with_index = pd.Series(data, index=custom_index)
print("创建时指定索引的Series:")
print(series_with_index)
通过NumPy数组创建的Series:
0    0.1
1    0.2
2    0.3
3    0.4
dtype: float64

通过字典创建的Series:
北京    2154
上海    2428
广州    1490
深圳    1303
dtype: int64

创建时指定索引的Series:
语文    88
数学    92
英语    79
物理    85
dtype: int64

思考:如果尝试将一个5行2列的NumPy二维数组传入pd.Series(),会发生什么?是报错还是能正常创建?动手试试看,能加深对Series一维特性的理解。

预览数据与查看属性

当处理大量数据时,我们通常不需要查看全部内容,只需预览头部或尾部的几行即可。Pandas提供了.head()和.tail()方法。

import pandas as pd
import numpy as np

# 创建一个包含100个随机数的Series(固定随机种子,保证每次演示输出一致)
np.random.seed(42)
ser_obj = pd.Series(np.random.rand(100), name='随机数序列')
ser_obj.index.name = '序号' # 给索引也起个名字

print("预览前5条数据 (head()):")
print(ser_obj.head())
print("\n预览后10条数据 (tail(10)):")
print(ser_obj.tail(10))
print("\nSeries的名称:", ser_obj.name)
print("索引的名称:", ser_obj.index.name)
print("\n索引对象:", ser_obj.index)
print("数据值 (NumPy数组):", type(ser_obj.values).__name__, "形状:", ser_obj.values.shape)
预览前5条数据 (head()):
序号
0    0.374540
1    0.950714
2    0.731994
3    0.598658
4    0.156019
Name: 随机数序列, dtype: float64

预览后10条数据 (tail(10)):
序号
90    0.119594
91    0.713245
92    0.760785
93    0.561277
94    0.770967
95    0.493796
96    0.522733
97    0.427541
98    0.025419
99    0.107891
Name: 随机数序列, dtype: float64

Series的名称: 随机数序列
索引的名称: 序号

索引对象: RangeIndex(start=0, stop=100, step=1, name='序号')
数据值 (NumPy数组): ndarray 形状: (100,)

从输出可以看到,ser_obj.values返回的是一个NumPy的ndarray,这印证了Pandas基于NumPy的事实。同时,为Series和索引设置名称,能让数据在展示和传递时含义更清晰。

通过索引访问数据

Series的强大之处在于可以通过索引标签方便地访问数据。访问方式主要有两种,推荐使用明确的方法以增加代码可读性。

import pandas as pd

# 创建一个示例Series
s_example = pd.Series([10, 20, 30, 40], index=['a', 'b', 'c', 'd'])
print("原始Series:")
print(s_example)

# 通过标签访问 (使用.loc推荐)
print("\n通过标签访问 s_example.loc['b']:", s_example.loc['b'])
print("通过标签访问 s_example['b']:", s_example['b']) # 等价写法

# 通过位置访问 (使用.iloc推荐)
print("\n通过位置访问 s_example.iloc[1]:", s_example.iloc[1])

# 旧写法 s[1]:pandas 3.0 起 [] 只按标签查找,不再回退到位置索引
try:
    print("通过位置访问 s_example[1]:", s_example[1])
except KeyError as e:
    print("s_example[1] 抛出 KeyError:", e, "(pandas 3.0 起 [] 只按标签查找,不再回退到位置)")

# 判断索引是否存在
print("\n判断索引'a'是否存在:", 'a' in s_example)
print("判断索引'f'是否存在:", 'f' in s_example)
原始Series:
a    10
b    20
c    30
d    40
dtype: int64

通过标签访问 s_example.loc['b']: 20
通过标签访问 s_example['b']: 20

通过位置访问 s_example.iloc[1]: 20
s_example[1] 抛出 KeyError: 1 (pandas 3.0 起 [] 只按标签查找,不再回退到位置)

判断索引'a'是否存在: True
判断索引'f'是否存在: False

关键点:

  • .loc[]:基于索引标签进行选择。s.loc['b']。
  • .iloc[]:基于整数位置进行选择。s.iloc[1]。
  • 直接使用方括号 s['b'] 按标签访问仍然可用;但在 pandas 3.0 中,s[1] 这类整数写法已不再回退到位置索引(旧版本对非整数索引会“回退”到位置,行为易混淆;新版本统一为「[] 只按标签查找」)。因此,强烈建议始终使用.loc和.iloc来使意图清晰。
  • Series可以看作一个“定长有序字典”,因此可以使用in关键字检查某个标签是否在索引中。

自动处理缺失数据

在实际数据中,缺失值非常常见。Pandas的一个便利特性是能够根据数据类型自动处理缺失值。

import pandas as pd
import numpy as np

# 字符串列表中包含None
countries = ['中国', '美国', '澳大利亚', None]
series_str = pd.Series(countries)
print("字符串类型Series处理None:")
print(series_str)
print("数据类型:", series_str.dtype)
print()

# 数值列表中包含None
numbers = [4, 5, 6, None]
series_num = pd.Series(numbers)
print("数值类型Series处理None:")
print(series_num)
print("数据类型:", series_num.dtype)
字符串类型Series处理None:
0      中国
1      美国
2    澳大利亚
3     NaN
dtype: str
数据类型: str

数值类型Series处理None:
0    4.0
1    5.0
2    6.0
3    NaN
dtype: float64
数据类型: float64

可以看到:

  • 对于字符串类型,pandas 3.0 默认使用专门的 str dtype,None 会统一显示为 NaN(缺失值标记)。
  • 对于数值类型,None 同样自动被转换为NaN(Not a Number,一个特殊的浮点数值),并且整个Series的数据类型会提升为float64,以容纳这个特殊的浮点数。

这种自动处理机制省去了我们手动检查和转换缺失值的麻烦,Pandas在后续也提供了丰富的方法(如dropna(), fillna())来专门处理这些缺失值。

📝 动手练一练

  1. 概念辨析:Series的.loc和.iloc有什么根本区别?在什么情况下使用方括号[]直接索引会产生歧义?请举例说明。
👉 点击查看参考答案

.loc 是基于索引的标签(label)进行数据选取,而.iloc是基于整数位置(integer position)进行选取。

当Series的索引也是整数时,使用方括号直接索引会产生歧义。例如:

import pandas as pd

s = pd.Series([100, 200, 300], index=[2, 4, 6])
# s[2] 这里是想获取标签为2的值(100),还是想获取位置为2(即第3个)的值(300)?

此时,使用s.loc[2]明确表示按标签获取(得到100),使用s.iloc[2]明确表示按位置获取(得到300),可以消除歧义。

  1. 动手实践:创建一个Series,其数据为[‘苹果’, ‘香蕉’, ‘橘子’, None],索引为[‘a’, ‘b’, ‘c’, ‘d’]。然后,尝试将其数据转换为NumPy数组(.values),观察输出结果。你发现了什么?这说明了Pandas和NumPy在处理缺失值上有什么不同?
👉 点击查看参考答案
import pandas as pd
import numpy as np

s_fruit = pd.Series(['苹果', '香蕉', '橘子', None], index=['a', 'b', 'c', 'd'])
print("Pandas Series:")
print(s_fruit)
print("\n转换为NumPy数组 (.values):")
print(s_fruit.values)
print("数组类型:", s_fruit.values.dtype)
Pandas Series:
a     苹果
b     香蕉
c     橘子
d    NaN
dtype: str

转换为NumPy数组 (.values):
<StringArray>
['苹果', '香蕉', '橘子', nan]
Length: 4, dtype: str
数组类型: str

发现与说明:在 pandas 3.0 中,字符串数据默认使用专门的 str dtype(不再是 object),None 在 Series 中统一显示为 NaN;.values 返回的是 StringArray(字符串扩展数组,元素为 nan)。这说明:

  • Pandas 的 Series 以 NumPy 为底座,但为字符串数据提供了专门的字符串数组(StringArray)扩展,并统一用 NaN 表示缺失值。
  • 纯 NumPy 的普通数组没有「缺失值」概念(只能用 np.nan + float dtype 或掩码数组等间接手段表示)。Pandas 在数据表示上比纯 NumPy 更贴近数据分析的实际需求,.isna() 等方法能统一识别缺失。

本章小结

本节我们开启了Pandas之旅,深入学习了其核心数据结构——Series。Series作为一维带标签的数组,是构建更复杂数据操作的基础。我们不仅掌握了创建Series的多种方法,还学会了如何查看其属性、预览数据以及通过标签或位置精准访问数据。更重要的是,我们看到了Pandas如何智能地处理缺失值,这为后续的真实数据分析扫清了一大障碍。

📋 行动清单

  • 在Python环境中,尝试用列表、字典和NumPy数组分别创建几个不同的Series,并使用.head()、.index、.values查看其内容。
  • 创建一个索引为字符串的Series,分别使用.loc[‘标签’]和.iloc[位置]来访问其中的元素,体会两者的区别。
  • 故意创建一个包含None的数值列表,并用其生成Series,观察Pandas是如何将其转换为NaN并改变数据类型的。

—— 小象教研组

配套资料 · 直接下载

课件、代码、数据集等配套资料全部免费,点击即可直接下载,无需分享或解锁。

  • 本节课件:数据结构-Series
    PDF · 478KB
    下载
  • 第5章配套代码包:Pandas 示例与数据集
    ZIP · 22.5MB
    下载
  • 全套课件打包(第1-5章)
    ZIP · 12.8MB
    下载
  • 全套课件打包(第6-8章)
    ZIP · 15MB
    下载
  • 实战数据集:AppleStore 应用商城分析
    ZIP · 329KB
    下载
  • 实战数据集:女性服装电商分析
    ZIP · 2.8MB
    下载
  • Python 数据分析环境搭建指南
    PDF · 2MB
    下载
  • Scrapy 安装教程
    PDF · 12.7MB
    下载
  • 附加实战项目:AppleStore 应用商城数据分析
    ZIP · 0.3MB · ipynb + CSV 数据
    下载
  • 附加实战项目:银行电话营销数据分析
    ZIP · 0.4MB · ipynb + CSV 数据
    下载
  • 附加实战项目:女性服装电商评论数据分析
    ZIP · 2.7MB · ipynb + CSV 数据
    下载
  • 附加实战项目:美国化学学会杂志数据分析
    ZIP · 34.2MB · ipynb + SQLite 数据库
    下载