写点什么

Pandas 之:Pandas 简洁教程

发布于: 2021 年 06 月 05 日

简介

pandas 是建立在 Python 编程语言之上的一种快速,强大,灵活且易于使用的开源数据分析和处理工具,它含有使数据清洗和分析⼯

作变得更快更简单的数据结构和操作⼯具。pandas 经常和其它⼯具⼀同使⽤,如数值计算⼯具 NumPy 和 SciPy,分析库 statsmodels 和 scikit-learn,和数据可视化库 matplotlib 等。

pandas 是基于 NumPy 数组构建的,虽然 pandas 采⽤了⼤量的 NumPy 编码⻛格,但⼆者最⼤的不同是 pandas 是专⻔为处理表格和混杂数据设计的。⽽NumPy 更适合处理统⼀的数值数组数据。

本文是关于 Pandas 的简洁教程。

对象创建

因为 Pandas 是基于 NumPy 数组来构建的,所以我们在引用的时候需要同时引用 Pandas 和 NumPy:

In [1]: import numpy as np
In [2]: import pandas as pd
复制代码

Pandas 中最主要的两个数据结构是 Series 和 DataFrame。

Series 和一维数组很相似,它是由 NumPy 的各种数据类型来组成的,同时还包含了和这组数据相关的 index。

我们来看一个 Series 的例子:

In [3]: pd.Series([1, 3, 5, 6, 8])Out[3]:0    11    32    53    64    8dtype: int64
复制代码

左边的是索引,右边的是值。因为我们在创建 Series 的时候并没有指定 index,所以 index 是从 0 开始到 n-1 结束。

Series 在创建的时候还可以传入 np.nan 表示空值:

In [4]: pd.Series([1, 3, 5, np.nan, 6, 8])Out[4]:0    1.01    3.02    5.03    NaN4    6.05    8.0dtype: float64
复制代码

DataFrame 是⼀个表格型的数据结构,它含有⼀组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。

DataFrame 既有⾏索引也有列索引,它可以被看做由 Series 组成的字典(共⽤同⼀个索引)。

看一个创建 DataFrame 的例子:

In [5]: dates = pd.date_range('20201201', periods=6)
In [6]: datesOut[6]:DatetimeIndex(['2020-12-01', '2020-12-02', '2020-12-03', '2020-12-04', '2020-12-05', '2020-12-06'], dtype='datetime64[ns]', freq='D')
复制代码

上面我们创建了一个 index 的 list。

然后使用这个 index 来创建一个 DataFrame:

In [7]:  pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list('ABCD'))Out[7]:                   A         B         C         D2020-12-01  1.536312 -0.318095 -0.737956  0.1433522020-12-02  1.325221  0.065641 -2.763370 -0.1305112020-12-03 -1.143560 -0.805807  0.174722  0.4270272020-12-04 -0.724206  0.050155 -0.648675 -0.6451662020-12-05  0.182411  0.956385  0.349465 -0.4840402020-12-06  1.857108  1.245928 -0.767316 -1.890586
复制代码

上面的 DataFrame 接收三个参数,第一个参数是 DataFrame 的表格数据,第二个参数是 index 的值,也可以看做是行名,第三个参数是列名。

还可以直接传入一个字典来创建一个 DataFrame:

In [9]: pd.DataFrame({'A': 1.,   ...:                         'B': pd.Timestamp('20201202'),   ...:                         'C': pd.Series(1, index=list(range(4)), dtype='float32'),   ...:                         'D': np.array([3] * 4, dtype='int32'),   ...:                         'E': pd.Categorical(["test", "train", "test", "train"]),   ...:                         'F': 'foo'})   ...:Out[9]:     A          B    C  D      E    F0  1.0 2020-12-02  1.0  3   test  foo1  1.0 2020-12-02  1.0  3  train  foo2  1.0 2020-12-02  1.0  3   test  foo3  1.0 2020-12-02  1.0  3  train  foo
复制代码

上面的 DataFrame 中,每个列都有不同的数据类型。

我们用个图片来更好的理解 DataFrame 和 Series:



它就像是 Excel 中的表格,带有行头和列头。

DataFrame 中的每一列都可以看做是一个 Series:



查看数据

创建好 Series 和 DataFrame 之后,我们就可以查看他们的数据了。

Series 可以通过 index 和 values 来获取其索引和值信息:

In [10]: data1 = pd.Series([1, 3, 5, np.nan, 6, 8])
In [12]: data1.indexOut[12]: RangeIndex(start=0, stop=6, step=1)
In [14]: data1.valuesOut[14]: array([ 1., 3., 5., nan, 6., 8.])
复制代码

DataFrame 可以看做是 Series 的集合,所以 DataFrame 带有更多的属性:

In [16]: df.head()Out[16]:                   A         B         C         D2020-12-01  0.446248 -0.060549 -0.445665 -1.3925022020-12-02 -1.119749 -1.659776 -0.618656  1.9715992020-12-03  0.610846  0.216937  0.821258  0.8058182020-12-04  0.490105  0.732421  0.547129 -0.4432742020-12-05 -0.475531 -0.853141  0.160017  0.986973
In [17]: df.tail(3)Out[17]: A B C D2020-12-04 0.490105 0.732421 0.547129 -0.4432742020-12-05 -0.475531 -0.853141 0.160017 0.9869732020-12-06 0.288091 -2.164323 0.193989 -0.197923
复制代码

head 跟 tail 分别取得 DataFrame 的头几行和尾部几行。

同样的 DataFrame 也有 index 和 columns:

In [19]: df.indexOut[19]:DatetimeIndex(['2020-12-01', '2020-12-02', '2020-12-03', '2020-12-04',               '2020-12-05', '2020-12-06'],              dtype='datetime64[ns]', freq='D')
In [20]: df.valuesOut[20]:array([[ 0.44624818, -0.0605494 , -0.44566462, -1.39250227], [-1.11974917, -1.65977552, -0.61865617, 1.97159943], [ 0.61084596, 0.2169369 , 0.82125808, 0.80581847], [ 0.49010504, 0.73242082, 0.54712889, -0.44327351], [-0.47553134, -0.85314134, 0.16001748, 0.98697257], [ 0.28809148, -2.16432292, 0.19398863, -0.19792266]])
复制代码

describe 方法可以对数据进行统计:

In [26]: df.describe()Out[26]:              A         B         C         Dcount  6.000000  6.000000  6.000000  6.000000mean   0.040002 -0.631405  0.109679  0.288449std    0.687872  1.128019  0.556099  1.198847min   -1.119749 -2.164323 -0.618656 -1.39250225%   -0.284626 -1.458117 -0.294244 -0.38193650%    0.367170 -0.456845  0.177003  0.30394875%    0.479141  0.147565  0.458844  0.941684max    0.610846  0.732421  0.821258  1.971599
复制代码

还可以对 DataFrame 进行转置:

In [27]: df.TOut[27]:   2020-12-01  2020-12-02  2020-12-03  2020-12-04  2020-12-05  2020-12-06A    0.446248   -1.119749    0.610846    0.490105   -0.475531    0.288091B   -0.060549   -1.659776    0.216937    0.732421   -0.853141   -2.164323C   -0.445665   -0.618656    0.821258    0.547129    0.160017    0.193989D   -1.392502    1.971599    0.805818   -0.443274    0.986973   -0.197923
复制代码

可以按行和按列进行排序:

In [28]: df.sort_index(axis=1, ascending=False)Out[28]:                   D         C         B         A2020-12-01 -1.392502 -0.445665 -0.060549  0.4462482020-12-02  1.971599 -0.618656 -1.659776 -1.1197492020-12-03  0.805818  0.821258  0.216937  0.6108462020-12-04 -0.443274  0.547129  0.732421  0.4901052020-12-05  0.986973  0.160017 -0.853141 -0.4755312020-12-06 -0.197923  0.193989 -2.164323  0.288091
In [29]: df.sort_values(by='B')Out[29]: A B C D2020-12-06 0.288091 -2.164323 0.193989 -0.1979232020-12-02 -1.119749 -1.659776 -0.618656 1.9715992020-12-05 -0.475531 -0.853141 0.160017 0.9869732020-12-01 0.446248 -0.060549 -0.445665 -1.3925022020-12-03 0.610846 0.216937 0.821258 0.8058182020-12-04 0.490105 0.732421 0.547129 -0.443274
复制代码

选择数据

通过 DataFrame 的列名,可以选择代表列的 Series:

In [30]: df['A']Out[30]:2020-12-01    0.4462482020-12-02   -1.1197492020-12-03    0.6108462020-12-04    0.4901052020-12-05   -0.4755312020-12-06    0.288091Freq: D, Name: A, dtype: float64
复制代码

通过切片可以选择行:

In [31]: df[0:3]Out[31]:                   A         B         C         D2020-12-01  0.446248 -0.060549 -0.445665 -1.3925022020-12-02 -1.119749 -1.659776 -0.618656  1.9715992020-12-03  0.610846  0.216937  0.821258  0.805818
复制代码

或者这样:

In [32]: df['20201202':'20201204']Out[32]:                   A         B         C         D2020-12-02 -1.119749 -1.659776 -0.618656  1.9715992020-12-03  0.610846  0.216937  0.821258  0.8058182020-12-04  0.490105  0.732421  0.547129 -0.443274
复制代码

loc 和 iloc

使用 loc 可以使用轴标签来选取数据。

In [33]: df.loc[:, ['A', 'B']]Out[33]:                   A         B2020-12-01  0.446248 -0.0605492020-12-02 -1.119749 -1.6597762020-12-03  0.610846  0.2169372020-12-04  0.490105  0.7324212020-12-05 -0.475531 -0.8531412020-12-06  0.288091 -2.164323
复制代码

前面是行的选择,后面是列的选择。

还可以指定 index 的名字:

In [34]: df.loc['20201202':'20201204', ['A', 'B']]Out[34]:                   A         B2020-12-02 -1.119749 -1.6597762020-12-03  0.610846  0.2169372020-12-04  0.490105  0.732421
复制代码

如果 index 的名字不是切片的话,将会给数据降维:

In [35]: df.loc['20201202', ['A', 'B']]Out[35]:A   -1.119749B   -1.659776Name: 2020-12-02 00:00:00, dtype: float64
复制代码

如果后面列是一个常量的话,直接返回对应的值:

In [37]: df.loc['20201202', 'A']Out[37]: -1.1197491665145112
复制代码

iloc 是根据值来选取数据,比如我们选择第三行:

In [42]: df.iloc[3]Out[42]:A    0.490105B    0.732421C    0.547129D   -0.443274Name: 2020-12-04 00:00:00, dtype: float64
复制代码

它其实和 df.loc[‘2020-12-04’]是等价的:

In [41]: df.loc['2020-12-04']Out[41]:A    0.490105B    0.732421C    0.547129D   -0.443274Name: 2020-12-04 00:00:00, dtype: float64
复制代码

同样可以传入切片:

In [43]: df.iloc[3:5, 0:2]Out[43]:                   A         B2020-12-04  0.490105  0.7324212020-12-05 -0.475531 -0.853141
复制代码

可以传入 list:

In [44]: df.iloc[[1, 2, 4], [0, 2]]Out[44]:                   A         C2020-12-02 -1.119749 -0.6186562020-12-03  0.610846  0.8212582020-12-05 -0.475531  0.160017
复制代码

取具体某个格子的值:

In [45]: df.iloc[1, 1]Out[45]: -1.6597755161871708
复制代码

布尔索引

DataFrame 还可以通过布尔值来进行索引,下面是找出列 A 中所有元素大于 0 的:

In [46]: df[df['A'] > 0]Out[46]:                   A         B         C         D2020-12-01  0.446248 -0.060549 -0.445665 -1.3925022020-12-03  0.610846  0.216937  0.821258  0.8058182020-12-04  0.490105  0.732421  0.547129 -0.4432742020-12-06  0.288091 -2.164323  0.193989 -0.197923
复制代码

或者找出整个 DF 中,值大于 0 的:

In [47]: df[df > 0]Out[47]:                   A         B         C         D2020-12-01  0.446248       NaN       NaN       NaN2020-12-02       NaN       NaN       NaN  1.9715992020-12-03  0.610846  0.216937  0.821258  0.8058182020-12-04  0.490105  0.732421  0.547129       NaN2020-12-05       NaN       NaN  0.160017  0.9869732020-12-06  0.288091       NaN  0.193989       NaN
复制代码

可以给 DF 添加一列:

In [48]: df['E'] = ['one', 'one', 'two', 'three', 'four', 'three']
In [49]: dfOut[49]: A B C D E2020-12-01 0.446248 -0.060549 -0.445665 -1.392502 one2020-12-02 -1.119749 -1.659776 -0.618656 1.971599 one2020-12-03 0.610846 0.216937 0.821258 0.805818 two2020-12-04 0.490105 0.732421 0.547129 -0.443274 three2020-12-05 -0.475531 -0.853141 0.160017 0.986973 four2020-12-06 0.288091 -2.164323 0.193989 -0.197923 three
复制代码

使用 isin()来进行范围值的判断判断:

In [50]: df[df['E'].isin(['two', 'four'])]Out[50]:                   A         B         C         D     E2020-12-03  0.610846  0.216937  0.821258  0.805818   two2020-12-05 -0.475531 -0.853141  0.160017  0.986973  four
复制代码

处理缺失数据

现在我们的 df 有 a,b,c,d,e 这 5 列,如果我们再给他加一列 f,那么 f 的初始值将会是 NaN:

In [55]: df.reindex(columns=list(df.columns) + ['F'])Out[55]:                   A         B         C         D      E   F2020-12-01  0.446248 -0.060549 -0.445665 -1.392502    one NaN2020-12-02 -1.119749 -1.659776 -0.618656  1.971599    one NaN2020-12-03  0.610846  0.216937  0.821258  0.805818    two NaN2020-12-04  0.490105  0.732421  0.547129 -0.443274  three NaN2020-12-05 -0.475531 -0.853141  0.160017  0.986973   four NaN2020-12-06  0.288091 -2.164323  0.193989 -0.197923  three NaN
复制代码

我们给前面的两个 F 赋值:

In [74]: df1.iloc[0:2,5]=1
In [75]: df1Out[75]: A B C D E F2020-12-01 0.446248 -0.060549 -0.445665 -1.392502 one 1.02020-12-02 -1.119749 -1.659776 -0.618656 1.971599 one 1.02020-12-03 0.610846 0.216937 0.821258 0.805818 two NaN2020-12-04 0.490105 0.732421 0.547129 -0.443274 three NaN2020-12-05 -0.475531 -0.853141 0.160017 0.986973 four NaN2020-12-06 0.288091 -2.164323 0.193989 -0.197923 three NaN
复制代码

可以 drop 所有为 NaN 的行:

In [76]: df1.dropna(how='any')Out[76]:                   A         B         C         D    E    F2020-12-01  0.446248 -0.060549 -0.445665 -1.392502  one  1.02020-12-02 -1.119749 -1.659776 -0.618656  1.971599  one  1.0
复制代码

可以填充 NaN 的值:

In [77]: df1.fillna(value=5)Out[77]:                   A         B         C         D      E    F2020-12-01  0.446248 -0.060549 -0.445665 -1.392502    one  1.02020-12-02 -1.119749 -1.659776 -0.618656  1.971599    one  1.02020-12-03  0.610846  0.216937  0.821258  0.805818    two  5.02020-12-04  0.490105  0.732421  0.547129 -0.443274  three  5.02020-12-05 -0.475531 -0.853141  0.160017  0.986973   four  5.02020-12-06  0.288091 -2.164323  0.193989 -0.197923  three  5.0
复制代码

可以对值进行判断:

In [78]:  pd.isna(df1)Out[78]:                A      B      C      D      E      F2020-12-01  False  False  False  False  False  False2020-12-02  False  False  False  False  False  False2020-12-03  False  False  False  False  False   True2020-12-04  False  False  False  False  False   True2020-12-05  False  False  False  False  False   True2020-12-06  False  False  False  False  False   True
复制代码

合并

DF 可以使用 Concat 来合并多个 df,我们先创建一个 df:

In [79]: df = pd.DataFrame(np.random.randn(10, 4))
In [80]: dfOut[80]: 0 1 2 30 1.089041 2.010142 -0.532527 0.9916691 1.303678 -0.614206 -1.358952 0.0062902 -2.663938 0.600209 -0.008845 -0.0369003 0.863718 -0.450501 1.325427 0.4173454 0.789239 -0.492630 0.873732 0.3759415 0.327177 0.010719 -0.085967 -0.5912676 -0.014350 1.372144 -0.688845 0.4227017 -3.355685 0.044306 -0.979253 -2.1842408 -0.051961 0.649734 1.156918 -0.2337259 -0.692530 0.057805 -0.030565 0.209416
复制代码

然后把 DF 拆成三部分:

In [81]: pieces = [df[:3], df[3:7], df[7:]]
复制代码

最后把使用 concat 把他们合起来:

In [82]: pd.concat(pieces)Out[82]:          0         1         2         30  1.089041  2.010142 -0.532527  0.9916691  1.303678 -0.614206 -1.358952  0.0062902 -2.663938  0.600209 -0.008845 -0.0369003  0.863718 -0.450501  1.325427  0.4173454  0.789239 -0.492630  0.873732  0.3759415  0.327177  0.010719 -0.085967 -0.5912676 -0.014350  1.372144 -0.688845  0.4227017 -3.355685  0.044306 -0.979253 -2.1842408 -0.051961  0.649734  1.156918 -0.2337259 -0.692530  0.057805 -0.030565  0.209416
复制代码

还可以使用 join 来进行类似 SQL 的合并:

In [83]: left = pd.DataFrame({'key': ['foo', 'foo'], 'lval': [1, 2]})
In [84]: right = pd.DataFrame({'key': ['foo', 'foo'], 'rval': [4, 5]})
In [85]: leftOut[85]: key lval0 foo 11 foo 2
In [86]: rightOut[86]: key rval0 foo 41 foo 5
In [87]: pd.merge(left, right, on='key')Out[87]: key lval rval0 foo 1 41 foo 1 52 foo 2 43 foo 2 5
复制代码

分组

先看上面的 DF:

In [99]: df2Out[99]:   key  lval  rval0  foo     1     41  foo     1     52  foo     2     43  foo     2     5
复制代码

我们可以根据 key 来进行 group,从而进行 sum:

In [98]: df2.groupby('key').sum()Out[98]:     lval  rvalkeyfoo     6    18
复制代码

group 还可以按多个列进行:

In [100]: df2.groupby(['key','lval']).sum()Out[100]:          rvalkey lvalfoo 1        9    2        9
复制代码

本文已收录于 http://www.flydean.com/01-python-pandas-overview/

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!

欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!

发布于: 2021 年 06 月 05 日阅读数: 14
用户头像

关注公众号:程序那些事,更多精彩等着你! 2020.06.07 加入

最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧,尽在公众号:程序那些事!

评论

发布
暂无评论
Pandas之:Pandas简洁教程