第144集:Pandas Series

一、Pandas简介

Pandas是Python中用于数据处理和分析的强大库,它提供了灵活且高效的数据结构,使得数据处理变得简单直观。Pandas的核心数据结构包括:

  • Series:一维带标签的数组
  • DataFrame:二维带标签的表格数据结构

本集我们将重点学习Pandas Series的基本概念和操作。

二、什么是Series

Series是Pandas中最基本的数据结构之一,它是一个一维带标签的数组,可以存储任意数据类型(整数、浮点数、字符串、布尔值等)。

Series的特点:

  1. 带标签:每个元素都有一个标签(索引)
  2. 异质数据:可以包含不同类型的数据
  3. 强大的索引:支持多种索引方式
  4. 缺失值处理:内置对缺失值的处理机制
  5. 丰富的操作:提供大量的统计和数据处理方法

三、创建Series

1. 从列表创建

import pandas as pd

# 从列表创建Series
data = [1, 2, 3, 4, 5]
s = pd.Series(data)
print(s)

# 输出:
# 0    1
# 1    2
# 2    3
# 3    4
# 4    5
# dtype: int64

2. 指定索引

# 指定索引
index = ['a', 'b', 'c', 'd', 'e']
s = pd.Series(data, index=index)
print(s)

# 输出:
# a    1
# b    2
# c    3
# d    4
# e    5
# dtype: int64

3. 从字典创建

# 从字典创建Series
data = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
s = pd.Series(data)
print(s)

# 输出:
# a    1
# b    2
# c    3
# d    4
# e    5
# dtype: int64

4. 从标量值创建

# 从标量值创建Series
s = pd.Series(5, index=['a', 'b', 'c', 'd', 'e'])
print(s)

# 输出:
# a    5
# b    5
# c    5
# d    5
# e    5
# dtype: int64

5. 从NumPy数组创建

import numpy as np

# 从NumPy数组创建Series
arr = np.array([1, 2, 3, 4, 5])
s = pd.Series(arr)
print(s)

# 输出:
# 0    1
# 1    2
# 2    3
# 3    4
# 4    5
# dtype: int64

四、Series的属性

Series具有多种属性,可以帮助我们了解Series的基本信息:

1. values:获取Series的值

s = pd.Series([1, 2, 3, 4, 5], index=['a', 'b', 'c', 'd', 'e'])
print(s.values)
# 输出:[1 2 3 4 5]

2. index:获取Series的索引

print(s.index)
# 输出:Index(['a', 'b', 'c', 'd', 'e'], dtype='object')

3. dtype:获取Series的数据类型

print(s.dtype)
# 输出:int64

4. shape:获取Series的形状

print(s.shape)
# 输出:(5,)

5. size:获取Series的元素数量

print(s.size)
# 输出:5

6. ndim:获取Series的维度

print(s.ndim)
# 输出:1

7. empty:检查Series是否为空

print(s.empty)
# 输出:False

五、Series的索引和切片

1. 基于标签的索引(标签索引)

s = pd.Series([1, 2, 3, 4, 5], index=['a', 'b', 'c', 'd', 'e'])

# 单个标签索引
print(s['a'])
# 输出:1

# 多个标签索引
print(s[['a', 'c', 'e']])
# 输出:
# a    1
# c    3
# e    5
# dtype: int64

2. 基于位置的索引(位置索引)

# 使用iloc属性进行位置索引
s = pd.Series([1, 2, 3, 4, 5], index=['a', 'b', 'c', 'd', 'e'])

# 单个位置索引
print(s.iloc[0])
# 输出:1

# 多个位置索引
print(s.iloc[[0, 2, 4]])
# 输出:
# a    1
# c    3
# e    5
# dtype: int64

3. 切片操作

# 基于标签的切片(包含end)
s = pd.Series([1, 2, 3, 4, 5], index=['a', 'b', 'c', 'd', 'e'])
print(s['a':'c'])
# 输出:
# a    1
# b    2
# c    3
# dtype: int64

# 基于位置的切片(不包含end)
print(s.iloc[0:3])
# 输出:
# a    1
# b    2
# c    3
# dtype: int64

六、Series的基本操作

1. 算术运算

Series支持所有基本的算术运算,运算时会自动对齐索引:

s1 = pd.Series([1, 2, 3, 4, 5], index=['a', 'b', 'c', 'd', 'e'])
s2 = pd.Series([5, 4, 3, 2, 1], index=['a', 'b', 'c', 'd', 'e'])

# 加法
print(s1 + s2)
# 输出:
# a    6
# b    6
# c    6
# d    6
# e    6
# dtype: int64

# 减法
print(s1 - s2)
# 输出:
# a   -4
# b   -2
# c    0
# d    2
# e    4
# dtype: int64

# 乘法
print(s1 * s2)
# 输出:
# a    5
# b    8
# c    9
# d    8
# e    5
# dtype: int64

# 除法
print(s1 / s2)
# 输出:
# a    0.2
# b    0.5
# c    1.0
# d    2.0
# e    5.0
# dtype: float64

2. 比较运算

s = pd.Series([1, 2, 3, 4, 5], index=['a', 'b', 'c', 'd', 'e'])

print(s > 3)
# 输出:
# a    False
# b    False
# c    False
# d     True
# e     True
# dtype: bool

print(s == 3)
# 输出:
# a    False
# b    False
# c     True
# d    False
# e    False
# dtype: bool

3. 逻辑运算

s = pd.Series([1, 2, 3, 4, 5], index=['a', 'b', 'c', 'd', 'e'])

# 使用&(与)、|(或)、~(非)进行逻辑运算
print((s > 2) & (s < 5))
# 输出:
# a    False
# b    False
# c     True
# d     True
# e    False
# dtype: bool

print((s < 2) | (s > 4))
# 输出:
# a     True
# b    False
# c    False
# d    False
# e     True
# dtype: bool

七、Series的统计功能

Pandas Series提供了丰富的统计方法:

1. 基本统计量

s = pd.Series([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])

print(f"求和:{s.sum()}")
print(f"平均值:{s.mean()}")
print(f"中位数:{s.median()}")
print(f"最大值:{s.max()}")
print(f"最小值:{s.min()}")
print(f"标准差:{s.std()}")
print(f"方差:{s.var()}")
print(f"计数:{s.count()}")
print(f"25%分位数:{s.quantile(0.25)}")
print(f"50%分位数:{s.quantile(0.5)}")
print(f"75%分位数:{s.quantile(0.75)}")

# 输出:
# 求和:55
# 平均值:5.5
# 中位数:5.5
# 最大值:10
# 最小值:1
# 标准差:3.0276503540974917
# 方差:9.166666666666666
# 计数:10
# 25%分位数:3.25
# 50%分位数:5.5
# 75%分位数:7.75

2. 累计统计

s = pd.Series([1, 2, 3, 4, 5])

print(f"累计和:{s.cumsum()}")
print(f"累计积:{s.cumprod()}")
print(f"累计最大值:{s.cummax()}")
print(f"累计最小值:{s.cummin()}")

# 输出:
# 累计和:0    1
# 1    3
# 2    6
# 3   10
# 4   15
# dtype: int64
# 累计积:0     1
# 1     2
# 2     6
# 3    24
# 4   120
# dtype: int64
# 累计最大值:0    1
# 1    2
# 2    3
# 3    4
# 4    5
# dtype: int64
# 累计最小值:0    1
# 1    1
# 2    1
# 3    1
# 4    1
# dtype: int64

3. 描述性统计

s = pd.Series([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
print(s.describe())

# 输出:
# count    10.000000
# mean      5.500000
# std       3.027650
# min       1.000000
# 25%       3.250000
# 50%       5.500000
# 75%       7.750000
# max      10.000000
# dtype: float64

八、Series的缺失值处理

在实际数据中,经常会遇到缺失值。Pandas提供了处理缺失值的方法:

1. 检查缺失值

s = pd.Series([1, 2, None, 4, 5, None], index=['a', 'b', 'c', 'd', 'e', 'f'])

print(s.isnull())
# 输出:
# a    False
# b    False
# c     True
# d    False
# e    False
# f     True
# dtype: bool

print(s.notnull())
# 输出:
# a     True
# b     True
# c    False
# d     True
# e     True
# f    False
# dtype: bool

2. 过滤缺失值

# 使用dropna()方法过滤缺失值
print(s.dropna())
# 输出:
# a    1.0
# b    2.0
# d    4.0
# e    5.0
# dtype: float64

# 使用布尔索引过滤缺失值
print(s[s.notnull()])
# 输出:
# a    1.0
# b    2.0
# d    4.0
# e    5.0
# dtype: float64

3. 填充缺失值

# 使用fillna()方法填充缺失值

# 用固定值填充
print(s.fillna(0))
# 输出:
# a    1.0
# b    2.0
# c    0.0
# d    4.0
# e    5.0
# f    0.0
# dtype: float64

# 用前一个值填充(向前填充)
print(s.fillna(method='ffill'))
# 输出:
# a    1.0
# b    2.0
# c    2.0
# d    4.0
# e    5.0
# f    5.0
# dtype: float64

# 用后一个值填充(向后填充)
print(s.fillna(method='bfill'))
# 输出:
# a    1.0
# b    2.0
# c    4.0
# d    4.0
# e    5.0
# f    NaN
# dtype: float64

# 用平均值填充
print(s.fillna(s.mean()))
# 输出:
# a    1.0
# b    2.0
# c    3.0
# d    4.0
# e    5.0
# f    3.0
# dtype: float64

九、Series的其他操作

1. 修改索引

s = pd.Series([1, 2, 3, 4, 5], index=['a', 'b', 'c', 'd', 'e'])

# 直接修改索引
new_index = ['A', 'B', 'C', 'D', 'E']
s.index = new_index
print(s)
# 输出:
# A    1
# B    2
# C    3
# D    4
# E    5
# dtype: int64

# 使用rename()方法修改索引
# 可以传入一个字典来部分修改索引
s = s.rename({'A': 'a', 'B': 'b'})
print(s)
# 输出:
# a    1
# b    2
# C    3
# D    4
# E    5
# dtype: int64

2. 排序

s = pd.Series([3, 1, 4, 1, 5, 9, 2, 6], index=['c', 'a', 'd', 'a', 'e', 'i', 'b', 'f'])

# 按值排序
print(s.sort_values())
# 输出:
# a    1
# a    1
# b    2
# c    3
# d    4
# e    5
# f    6
# i    9
# dtype: int64

# 按索引排序
print(s.sort_index())
# 输出:
# a    1
# a    1
# b    2
# c    3
# d    4
# e    5
# f    6
# i    9
# dtype: int64

3. 唯一值

s = pd.Series([1, 2, 2, 3, 3, 3, 4, 4, 4, 4])

print(s.unique())
# 输出:[1 2 3 4]

print(s.nunique())
# 输出:4

# 计算每个值的出现次数
print(s.value_counts())
# 输出:
# 4    4
# 3    3
# 2    2
# 1    1
# dtype: int64

4. 应用函数

s = pd.Series([1, 2, 3, 4, 5])

# 使用apply()方法应用函数
doubled = s.apply(lambda x: x * 2)
print(doubled)
# 输出:
# 0     2
# 1     4
# 2     6
# 3     8
# 4    10
# dtype: int64

# 使用map()方法映射值
mapped = s.map({1: 'one', 2: 'two', 3: 'three', 4: 'four', 5: 'five'})
print(mapped)
# 输出:
# 0      one
# 1      two
# 2    three
# 3     four
# 4     five
# dtype: object

十、案例分析:销售数据统计

问题描述

假设有一个商店的月度销售数据,包含12个月的销售额(单位:万元):

月份 销售额
一月 25
二月 30
三月 35
四月 28
五月 32
六月 36
七月 38
八月 34
九月 40
十月 42
十一月 45
十二月 50

请使用Pandas Series分析这些数据:

  1. 计算年度总销售额
  2. 计算月平均销售额
  3. 找出销售额最高和最低的月份
  4. 计算销售额超过35万元的月份
  5. 计算销售额的标准差

解决方案

import pandas as pd

# 创建销售数据Series
months = ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月']
sales = [25, 30, 35, 28, 32, 36, 38, 34, 40, 42, 45, 50]

sales_series = pd.Series(sales, index=months)
print("月度销售数据:")
print(sales_series)
print()

# 1. 年度总销售额
total_sales = sales_series.sum()
print(f"1. 年度总销售额:{total_sales}万元")

# 2. 月平均销售额
avg_sales = sales_series.mean()
print(f"2. 月平均销售额:{avg_sales:.2f}万元")

# 3. 销售额最高和最低的月份
highest_month = sales_series.idxmax()
highest_sales = sales_series.max()
lowest_month = sales_series.idxmin()
lowest_sales = sales_series.min()
print(f"3. 销售额最高的月份:{highest_month},销售额:{highest_sales}万元")
print(f"   销售额最低的月份:{lowest_month},销售额:{lowest_sales}万元")

# 4. 销售额超过35万元的月份
high_sales_months = sales_series[sales_series > 35]
print(f"4. 销售额超过35万元的月份:")
print(high_sales_months)

# 5. 销售额的标准差
std_sales = sales_series.std()
print(f"5. 销售额的标准差:{std_sales:.2f}万元")

# 6. 计算月度销售额的增长率
print(f"6. 月度销售额增长率:")
growth_rate = sales_series.pct_change() * 100
print(growth_rate.round(2))

输出结果

月度销售数据:
一月     25
二月     30
三月     35
四月     28
五月     32
六月     36
七月     38
八月     34
九月     40
十月     42
十一月    45
十二月    50
dtype: int64

1. 年度总销售额:435万元
2. 月平均销售额:36.25万元
3. 销售额最高的月份:十二月,销售额:50万元
   销售额最低的月份:一月,销售额:25万元
4. 销售额超过35万元的月份:
六月     36
七月     38
九月     40
十月     42
十一月    45
十二月    50
dtype: int64
5. 销售额的标准差:7.33万元
6. 月度销售额增长率:
一月      NaN
二月     20.00
三月     16.67
四月    -20.00
五月     14.29
六月     12.50
七月      5.56
八月    -10.53
九月     17.65
十月      5.00
十一月     7.14
十二月    11.11
dtype: float64

十一、总结

本节课我们学习了Pandas Series的基本概念和操作:

  1. Series的创建:从列表、字典、标量、NumPy数组等创建Series
  2. Series的属性:values、index、dtype、shape、size等
  3. Series的索引和切片:基于标签和位置的索引方式
  4. Series的基本操作:算术运算、比较运算、逻辑运算
  5. Series的统计功能:求和、平均值、中位数、标准差等
  6. Series的缺失值处理:检查、过滤、填充缺失值
  7. Series的其他操作:修改索引、排序、唯一值、应用函数
  8. 实际应用案例:销售数据统计分析

Series是Pandas的基础数据结构,掌握Series的操作对于学习Pandas DataFrame和数据分析非常重要。下一节课,我们将学习Pandas的另一个核心数据结构——DataFrame。

十二、练习

  1. 创建一个Series,包含10个随机整数(范围1-100),并使用字母作为索引

  2. 对上述Series进行以下操作:

    • 计算最大值、最小值、平均值和标准差
    • 找出大于50的值
    • 按值降序排序
    • 计算累计和
  3. 创建一个包含缺失值的Series,并进行以下操作:

    • 检查缺失值
    • 使用前一个值填充缺失值
    • 使用平均值填充缺失值
  4. 假设有一周的天气数据(摄氏度):

    • 周一:22
    • 周二:25
    • 周三:23
    • 周四:24
    • 周五:26
    • 周六:28
    • 周日:27

    使用Series分析这些数据:

    • 计算平均温度
    • 找出最高温度的日期
    • 计算温度的变化率
    • 将温度转换为华氏度(华氏度 = 摄氏度 × 9/5 + 32)

扩展阅读

« 上一篇 NumPy数组操作 下一篇 » Pandas DataFrame