Python 数据处理(三)——pd.Series
前言
对于如何使用 R
来处理表格数据,相信你已经学习到很多了。
下面我们的重点是介绍如何在 Python
中处理表格型数据,提到 Python
数据处理,那就不得不说 pandas
了。
pandas
是 Python
数据处理的核心库,提供了快速、灵活、明确的数据结构,能够简单直接地处理结构性和关系型数据。
panda
适用于很多不同类型的数据:
- 具有不同类型的列的表格数据,如
Excel
和SQL
表 - 有序和无序(不一定是固定频率)的时间序列数据
- 具有行和列标签的任意矩阵数据(同类型或异构数据)
- 任何其他形式的观察/统计数据集。数据实际上根本不需要标记就可以放置到
pandas
数据结构中
Pandas
主要的数据结构是 Series
(一维)与 DataFrame
(二维),使用这两种数据结构就足以应对金融、统计、社会科学、工程等领域里的大多数数据了。
相较于 R
语言的 data.frame
,DataFrame
提供了更加丰富的功能。
Pandas
是基于 NumPy
开发的,可以与其它第三方科学计算库完美集成。
能够熟练使用 pandas
,处理数据将是事半功倍的,它的种种优点就不一一介绍了,下面开始正题吧。
安装
如果你系统中安装的是 Anaconda
环境的话,会自动安装 pandas
、numpy
、matplotlib
等常用的数据科学相关的库。
如果没有使用 Anaconda
的话可以使用
pip install pandas
一般我是推荐使用 Anaconda
环境的,是真的方便。还不知道如何安装配置 Anaconda
的话,可以找到我前面的文章,里面有详细的讲解。
数据结构
本节,我们先开始介绍 pandas
的基础数据结构
当然啦,使用这个包肯定得先导入了,同时我们也会使用到 numpy
中的一些函数,标准的导入方式是
In [1]: import numpy as np
In [2]: import pandas as pd
1. Series
Series
是带标签的一维数组,可以存储任意数据类型,如整数、浮点数、字符串、Python
对象等类型的数据。轴标签称为索引(index
),可以使用 pd.Series
函数来创建
>>> s = pd.Series(data, index=index)
其中,data
可以是
-
python
字典 - 多维数组
- 标量值(如
5
)
index
是对应的标签列表。根据不同的数据类型,分为以下几种情况:
多维数组
当 data
是多维数组时,index
长度必须与 data
长度一致。如果没有指定 index
参数,会自动创建递增的数值型索引,即 [0, ..., len(data) - 1]
In [3]: s = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])
In [4]: s
Out[4]:
a 0.469112
b -0.282863
c -1.509059
d -1.135632
e 1.212112
dtype: float64
In [5]: s.index
Out[5]: Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
In [6]: pd.Series(np.random.randn(5))
Out[6]:
0 -0.173215
1 0.119209
2 -1.044236
3 -0.861849
4 -2.104569
dtype: float64
注意:Pandas
的索引值是可以重复,如果使用不支持重复索引的操作会触发异常。
In [7]: pd.Series(np.random.randn(5), index=['a', 'b', 'd', 'd', 'e'])
Out[7]:
a 0.624372
b 0.173827
d 0.078082
d 0.765597
e 0.631827
dtype: float64
字典
可以使用字典实例化 Series
:
In [8]: d = {'b': 1, 'a': 0, 'c': 2}
In [9]: pd.Series(d)
Out[9]:
b 1
a 0
c 2
dtype: int64
注意:当 data
为字典,且未设置 index
参数时,如果 Python
的版本 >= 3.6 且 Pandas
的版本 >= 0.23
,Series
会按字典的插入顺序对索引排序。
在其他版本中 Series
会按字典的键(key
)的字母顺序排序列表。
也就是说,如果我们的 Python < 3.6
或 Pandas < 0.23
,上面的结果将是
a 0
b 1
c 2
dtype: int64
如果设置了 index
参数,会将 data
的数据根据 index
的顺序排序显示,不存在的值会复制为 NaN
In [10]: d = {'a': 0., 'b': 1., 'c': 2.}
In [11]: pd.Series(d, index=['b', 'c', 'd', 'a'])
Out[11]:
b 1.0
c 2.0
d NaN
a 0.0
dtype: float64
注意:在 pandas
中使用 NaN(Not a Number)
表示缺失值
标量值
如果 data
是标量值,那么必须设置索引值。Series
会按索引的长度重复该标量值。
In [12]: pd.Series(5., index=['a', 'b', 'c', 'd', 'e'])
Out[12]:
a 5.0
b 5.0
c 5.0
d 5.0
e 5.0
dtype: float64
Series 类似 numpy 的 ndarray
Series
的行为与 ndarray
类似,支持大部分的 NumPy
函数,同时还支持索引切片。
In [13]: s[0]
Out[13]: -1.9744628992708957
In [14]: s[:3]
Out[14]:
a -1.974463
b 1.926031
c 0.659861
dtype: float64
In [15]: s[s > s.median()]
Out[15]:
b 1.926031
e 1.077661
dtype: float64
In [16]: s[[4, 3, 1]]
Out[16]:
e 1.077661
d -1.386355
b 1.926031
dtype: float64
In [17]: np.exp(s)
Out[17]:
a 0.138836
b 6.862223
c 1.934524
d 0.249985
e 2.937800
dtype: float64
注意:我们可以使用 s[[4, 3, 1]]
这中传递列表的方式提取指定位置的值,还可以是重复的值,会重复提取
>>> s[[4, 3, 1, 1]]
e 1.077661
d -1.386355
b 1.926031
b 1.926031
dtype: float64
我们可以使用 dtype
属性获取数据的类型
In [18]: s.dtype
Out[18]: dtype('float64')
使用 astype()
设置数据的类型
In [19]: s.astype(str)
Out[19]:
a -1.9744628992708957
b 1.9260314025924432
c 0.6598612596804069
d -1.3863546449807986
e 1.0776610911873974
dtype: object
我们可以将 Series
转换为 array
或 numpy
数组
In [20]: s.array
Out[20]:
<PandasArray>
[-1.9744628992708957, 1.9260314025924432, 0.6598612596804069,
-1.3863546449807986, 1.0776610911873974]
Length: 5, dtype: float64
In [21]: s.to_numpy()
Out[21]: array([-1.9744629 , 1.9260314 , 0.65986126, -1.38635464, 1.07766109])
Series 也类似字典
Series
类似字典,可以用索引标签提取值或设置对应的值
In [22]: s['b']
Out[22]: 1.9260314025924432
In [23]: s['e'] = 12.
In [24]: s
Out[24]:
a -1.974463
b 1.926031
c 0.600000
d -1.386355
e 12.000000
dtype: float64
In [25]: 'e' in s
Out[25]: True
In [26]: 'f' in s
Out[26]: False
如果想要访问的标签不存在,会引发错误
In [27]: s[f]
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-28-c86c4a9a4a10> in <module>
----> 1 s[f]
NameError: name 'f' is not defined
也可以使用 get
方法提取 Series
里标签对应的值,当标签不存在时返回 None
或指定其他值
In [28]: s.get('f')
In [29]: s.get('f', np.nan)
Out[29]: nan
Series 支持矢量操作
Series
支持大多数数组操作
In [30]: s + s
Out[30]:
a -3.948926
b 3.852063
c 1.200000
d -2.772709
e 24.000000
dtype: float64
In [31]: s * 2
Out[31]:
a -3.948926
b 3.852063
c 1.200000
d -2.772709
e 24.000000
dtype: float64
Series
之间的操作会自动对齐标签数据,因此,不用顾及执行计算操作的 Series
是否有相同的标签。
In [32]: s[1:] + s[:-1]
Out[32]:
a NaN
b 3.852063
c 1.200000
d -2.772709
e NaN
dtype: float64
无法对应上的标签的运算结果会标记为 NaN
,计算结果会是所有涉及到的标签的并集
这样我们就无需编写代码显式对齐数据,为数据分析和研究提供了巨大的自由度和灵活性
注意:默认让不同索引对象操作的结果生成索引并集,是为了避免信息的丢失,当然我们也可以使用 drop
方法删除包含缺失值的标签。
名称属性
Series
支持 name
属性:
In [33]: s = pd.Series(np.random.randn(5), name='something')
In [34]: s
Out[34]:
0 1.926419
1 1.175251
2 -0.568534
3 -0.014069
4 1.401082
Name: something, dtype: float64
In [35]: s.name
Out[35]: 'something'
一般情况下,Series
自动分配 name
属性,特别是从 DataFrame
提取一维数据切片时。
可以使用 rename
方法对 Series
重命名
In [36]: s2 = s.rename("different")
In [37]: s2.name
Out[37]: 'different'