pandas 备忘

Pandas使用备忘,不定时更新。Pandas是一个开源的数据分析工具和数据结构。

参考资料

遇到困难时,请首先查阅下面的资料

主要数据类型

首先你需要引入Pandas

1
2
import numpy as np
import pandas as pd

需要时刻牢记在心的信条:数据和标签的对应关系是固有的。数据和标签的联系,除非被手动明确打破,否则永远不会被破坏。
Here is a basic tenet to keep in mind: data alignment is intrinsic. The link between labels and data will not be broken unless done so explicitly by you.

Series

Series是一维的、拥有标签的数组。它可以存放任何类型的数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 通过ndarray创建
s = pd.Series(np.random.randn(5), index=['a', 'b', 'c', 'd', 'e'])
s = pd.Series(np.random.randn(5)) # create index from 0 automatically
# 通过dict创建
d = {'a' : 0., 'b' : 1., 'c' : 2.}
pd.Series(d)
# a 0.0
# b 1.0
# c 2.0
# dtype: float64
pd.Series(d, index=['b', 'c', 'd', 'a'])
# b 1.0
# c 2.0
# d NaN
# a 0.0
# dtype: float64

注意,Pandas允许多个标签重复。但是如果对这样的对象进行了不支持多标签重复的操作,Pandas会弹出错误。

Series支持类似于ndarray的操作。更多关于下标操作请参考

1
2
3
4
5
6
7
8
9
# 下标访问
s[0]
# 范围访问
s[:3]
s[[4, 3, 1]]
# 条件范围
s[s > s.median()]
# 数学计算
np.exp(s)

Series还支持类似字典的操作。

1
2
3
4
5
6
7
s['a']
s['e']
'e' in s
'f' in s
# 利用get方法,缺失标签会返回None,或者你可以指定默认返回值
s.get('f')
s.get('f', np.nan)

Series也支持类似于vector的操作。需要注意的是,Series操作默认是标签对齐的:

1
2
3
4
5
s + s
s * 2
# 标签对齐
s[1:] + s[:-1]
# s: NaN, -0.5657, -3.0181, -2.2713, NaN

对于标签不同Series的操作,会返回包含它们标签并集的Series。

DataFrame

DataFrame是一种二维的、带有标签的数据结构。它记录多列可能拥有不同类型的数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
# 通过Series字典创建
d = {'one' : pd.Series([1., 2., 3.], index=['a', 'b', 'c']),
'two' : pd.Series([1., 2., 3., 4.], index=['a', 'b', 'c', 'd'])}
df = pd.DataFrame(d)
pd.DataFrame(d, index=['d', 'b', 'a'])
pd.DataFrame(d, index=['d', 'b', 'a'], columns=['two', 'three'])
# 通过ndarrays/lists字典创建
d = {'one' : [1., 2., 3., 4.],
'two' : [4., 3., 2., 1.]}
pd.DataFrame(d)
pd.DataFrame(d, index=['a', 'b', 'c', 'd'])

更多的创建方法请参考
行和列标签可以分别通过indexcolumns属性访问。

1
2
df.index # Index(['a', 'b', 'c', 'd'], dtype='object')
df.colums # Index(['one', 'two'], dtype='object')

列的选择、添加、删除

你可以将DataFrame看做一个Series的字典对象进行操作,比如选择列one可以df['one']。删除操作可以通过如下的方式进行:

1
2
3
del df['two']
# 或者
three = df.pop('three') # 类似于栈的弹出操作

新建或修改列可以

1
2
3
df['foo'] = 'bar' # 当接受一个标量时,会自动填充该列
df['one_trunc'] = df['one'][:2]
df.insert(1, 'bar', df['one']) # 插入一行

下标系统参考。基本的下表访问:

1
2
3
4
5
6
7
8
9
10
# Select column, return: Series
df[col]
# Select row by label, return: Series
df.loc[label]
# Select row by integer location, return: Series
df.iloc[loc]
# Slice rows, return: DataFrame
df[5:10]
#Select rows by boolean vector, return: DataFrame
df[bool_vec]

在对DataFrame和Series进行运算操作时,默认的行为是进行列和行间标签同时对齐。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
df = pd.DataFrame(np.random.randn(10, 4), columns=['A', 'B', 'C', 'D'])
df2 = pd.DataFrame(np.random.randn(7, 3), columns=['A', 'B', 'C'])
df + df2
# A B C D
# 0 0.0457 -0.0141 1.3809 NaN
# 1 -0.9554 -1.5010 0.0372 NaN
# 2 -0.6627 1.5348 -0.8597 NaN
# 3 -2.4529 1.2373 -0.1337 NaN
# 4 1.4145 1.9517 -2.3204 NaN
# 5 -0.4949 -1.6497 -1.0846 NaN
# 6 -1.0476 -0.7486 -0.8055 NaN
# 7 NaN NaN NaN NaN
# 8 NaN NaN NaN NaN
# 9 NaN NaN NaN NaN

然而对行(DataFrame间)进行操作时,默认的行为是对齐列,并在行方向传播。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
df = pd.DataFrame(np.random.randn(10, 4), columns=['A', 'B', 'C', 'D'])
# A B C D
# 0 0.172048 0.425696 0.030475 0.480378
# 1 0.755577 0.794145 0.165770 0.713358
# 2 0.679583 0.816424 0.819640 0.453055
# 3 0.196413 0.766271 0.819660 0.620422
# 4 0.532852 0.096903 0.789100 0.331398
# 5 0.648268 0.434176 0.867414 0.270507
# 6 0.114304 0.911944 0.730641 0.159977
# 7 0.239761 0.205195 0.844898 0.877213
# 8 0.787606 0.355654 0.251127 0.915917
# 9 0.118373 0.009234 0.698343 0.479416
df - df.iloc[0]
# A B C D
# 0 0.000000 0.000000 0.000000 0.000000
# 1 0.583530 0.368449 0.135295 0.232980
# 2 0.507535 0.390728 0.789165 -0.027323
# 3 0.024365 0.340576 0.789184 0.140044
# 4 0.360804 -0.328793 0.758625 -0.148980
# 5 0.476220 0.008481 0.836939 -0.209871
# 6 -0.057744 0.486249 0.700166 -0.320401
# 7 0.067713 -0.220501 0.814423 0.396834
# 8 0.615558 -0.070041 0.220652 0.435539
# 9 -0.053675 -0.416461 0.667867 -0.000962