10分钟了解潘大师-pandas
这是一个pandas简介, 适合新手. 更深入的学习请参考Cookbook.
通常情情况下使用前需要载入必须的包:
import numpy as np
import pandas as pd
创建对象
查看数据类型相关背景请查阅 Data Structure Intro section.
创建一个 Series 通过输入一个有值的列表, 让pandas自行生成整数索引(即类似excel行名) :
s = pd.Series([1, 3, 5, np.nan, 6, 8])
s
0 1.0
1 3.0
2 5.0
3 NaN
4 6.0
5 8.0
dtype: float64
通过NumPy array创建一个带有datetime index和labeled columns的DataFrame:
dates = pd.date_range('20130101', periods=6)
dates
DatetimeIndex(['2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04',
'2013-01-05', '2013-01-06'],
dtype='datetime64[ns]', freq='D')
df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list('ABCD'))
df
| A | B | C | D | |
|---|---|---|---|---|
| 2013-01-01 | 0.543095 | -0.137837 | 0.919448 | -0.793261 |
| 2013-01-02 | -0.620107 | -0.694901 | 0.126626 | -0.532929 |
| 2013-01-03 | 0.254118 | -0.780577 | -0.446656 | -1.336028 |
| 2013-01-04 | -1.956330 | 0.134201 | 0.217032 | -0.883961 |
| 2013-01-05 | -2.726763 | -1.783047 | 0.846121 | 1.874024 |
| 2013-01-06 | -1.083864 | -0.483887 | 0.449576 | -1.337890 |
通过传递可转换为series-like的字典对象来创建DataFrame。
df2 = pd.DataFrame({'A': 1.,
'B': pd.Timestamp('20130102'),
'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'})
df2
| A | B | C | D | E | F | |
|---|---|---|---|---|---|---|
| 0 | 1.0 | 2013-01-02 | 1.0 | 3 | test | foo |
| 1 | 1.0 | 2013-01-02 | 1.0 | 3 | train | foo |
| 2 | 1.0 | 2013-01-02 | 1.0 | 3 | test | foo |
| 3 | 1.0 | 2013-01-02 | 1.0 | 3 | train | foo |
生成的DataFrame每列的数据类型(dtypes)不同。
df2.dtypes
A float64
B datetime64[ns]
C float32
D int32
E category
F object
dtype: object
如果您使用的是IPython或Jupyter Notebook,可以启用tab自动列名(以及公共属性)的自动补全(像Rstudio一样,$,@等获取对象信息)。以下是将补全的属性的子集:
df2.attrs
{}

可见能自动补全出列名A和一些其它属性,例如.attrs查看数据类型,下面输出{}就要字典。
Viewing data
可通过查阅Basics section获取更多信息。
下面展示如何查看the top and bottom rows of the frame:
df.head()
| A | B | C | D | |
|---|---|---|---|---|
| 2013-01-01 | 0.543095 | -0.137837 | 0.919448 | -0.793261 |
| 2013-01-02 | -0.620107 | -0.694901 | 0.126626 | -0.532929 |
| 2013-01-03 | 0.254118 | -0.780577 | -0.446656 | -1.336028 |
| 2013-01-04 | -1.956330 | 0.134201 | 0.217032 | -0.883961 |
| 2013-01-05 | -2.726763 | -1.783047 | 0.846121 | 1.874024 |
df.tail(3)
| A | B | C | D | |
|---|---|---|---|---|
| 2013-01-04 | -1.956330 | 0.134201 | 0.217032 | -0.883961 |
| 2013-01-05 | -2.726763 | -1.783047 | 0.846121 | 1.874024 |
| 2013-01-06 | -1.083864 | -0.483887 | 0.449576 | -1.337890 |
显示列名及索引信息index, columns:
df.index
DatetimeIndex(['2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04',
'2013-01-05', '2013-01-06'],
dtype='datetime64[ns]', freq='D')
df.columns
Index(['A', 'B', 'C', 'D'], dtype='object')
DataFrame.to_numpy()给出了被引用数据的NumPy的更详细资料。请注意,当您的 DataFrame 具有不同数据类型的列时,这可以是一个扩展操作,这归结为pandas和NumPy的根本区别:NumPy数组只有一个dtype对应一种数据类型,当您调用 DataFrame.to_numpy()时,pandas将找到可以保存其中所有数据类型的NumPy数据类型。这最终可能是object,这需要将每个值强制转换为Python对象。
对于df,我们所有浮点值的DataFrame,DataFrame.to_numpy()运算速度很快,不需要复制数据。
df.to_numpy()
array([[ 0.54309506, -0.13783679, 0.91944836, -0.79326112],
[-0.62010737, -0.6949011 , 0.12662585, -0.53292921],
[ 0.25411836, -0.78057745, -0.44665594, -1.33602824],
[-1.95633038, 0.13420114, 0.21703165, -0.88396081],
[-2.72676346, -1.78304699, 0.84612148, 1.87402363],
[-1.08386413, -0.48388722, 0.44957561, -1.33789037]])
而df2, 因为这个数据框的不同列有多种数据类型因此转换起来相对比较费时(DataFrame.to_numpy() is relatively expensive)。
df2.to_numpy()
array([[1.0, Timestamp('2013-01-02 00:00:00'), 1.0, 3, 'test', 'foo'],
[1.0, Timestamp('2013-01-02 00:00:00'), 1.0, 3, 'train', 'foo'],
[1.0, Timestamp('2013-01-02 00:00:00'), 1.0, 3, 'test', 'foo'],
[1.0, Timestamp('2013-01-02 00:00:00'), 1.0, 3, 'train', 'foo']],
dtype=object)
Note
DataFrame.to_numpy()does not include the index or column labels in the output.
describe() 函数展示数据的统计摘要(计数,最大,最小,分位数等):
df.describe()
| A | B | C | D | |
|---|---|---|---|---|
| count | 6.000000 | 6.000000 | 6.000000 | 6.000000 |
| mean | -0.931642 | -0.624341 | 0.352025 | -0.501674 |
| std | 1.262818 | 0.663896 | 0.506465 | 1.205943 |
| min | -2.726763 | -1.783047 | -0.446656 | -1.337890 |
| 25% | -1.738214 | -0.759158 | 0.149227 | -1.223011 |
| 50% | -0.851986 | -0.589394 | 0.333304 | -0.838611 |
| 75% | 0.035562 | -0.224349 | 0.746985 | -0.598012 |
| max | 0.543095 | 0.134201 | 0.919448 | 1.874024 |
也可以像R一样用t对其进行转置(Transposing your data:)
df.T
| 2013-01-01 | 2013-01-02 | 2013-01-03 | 2013-01-04 | 2013-01-05 | 2013-01-06 | |
|---|---|---|---|---|---|---|
| A | 0.543095 | -0.620107 | 0.254118 | -1.956330 | -2.726763 | -1.083864 |
| B | -0.137837 | -0.694901 | -0.780577 | 0.134201 | -1.783047 | -0.483887 |
| C | 0.919448 | 0.126626 | -0.446656 | 0.217032 | 0.846121 | 0.449576 |
| D | -0.793261 | -0.532929 | -1.336028 | -0.883961 | 1.874024 | -1.337890 |
根据坐标轴来排序(Sorting by an axis)(0为横坐标,1为纵坐标,这个概念很重要!!!特别要apply函数使用中和R里的1,2一样的意思):
df.sort_index(axis=1, ascending=False)
| D | C | B | A | |
|---|---|---|---|---|
| 2013-01-01 | -0.793261 | 0.919448 | -0.137837 | 0.543095 |
| 2013-01-02 | -0.532929 | 0.126626 | -0.694901 | -0.620107 |
| 2013-01-03 | -1.336028 | -0.446656 | -0.780577 | 0.254118 |
| 2013-01-04 | -0.883961 | 0.217032 | 0.134201 | -1.956330 |
| 2013-01-05 | 1.874024 | 0.846121 | -1.783047 | -2.726763 |
| 2013-01-06 | -1.337890 | 0.449576 | -0.483887 | -1.083864 |
df.sort_index(axis=0, ascending=False)
| A | B | C | D | |
|---|---|---|---|---|
| 2013-01-06 | -1.083864 | -0.483887 | 0.449576 | -1.337890 |
| 2013-01-05 | -2.726763 | -1.783047 | 0.846121 | 1.874024 |
| 2013-01-04 | -1.956330 | 0.134201 | 0.217032 | -0.883961 |
| 2013-01-03 | 0.254118 | -0.780577 | -0.446656 | -1.336028 |
| 2013-01-02 | -0.620107 | -0.694901 | 0.126626 | -0.532929 |
| 2013-01-01 | 0.543095 | -0.137837 | 0.919448 | -0.793261 |
按值排序(参数ascending= False设为从大到小排,默认是从小到大):
df.sort_values(by='B',ascending= False)
| A | B | C | D | |
|---|---|---|---|---|
| 2013-01-04 | -1.956330 | 0.134201 | 0.217032 | -0.883961 |
| 2013-01-01 | 0.543095 | -0.137837 | 0.919448 | -0.793261 |
| 2013-01-06 | -1.083864 | -0.483887 | 0.449576 | -1.337890 |
| 2013-01-02 | -0.620107 | -0.694901 | 0.126626 | -0.532929 |
| 2013-01-03 | 0.254118 | -0.780577 | -0.446656 | -1.336028 |
| 2013-01-05 | -2.726763 | -1.783047 | 0.846121 | 1.874024 |
Selection(数据清洗常用)
虽然用于选择和设置的标准Python/Numpy表达式非常直观,对于交互式工作很方便,但对于学习写代码,我们推荐优化的pandas数据访问方法,
.at、.iat、.loc和.iloc。
查看Indexing and Selecting Data 和 MultiIndex / Advanced Indexing获取更多信息。
Getting
选择单个列,这将生成一个系列(Series),类似于df.A(跟R里面向量取子集,数据框取子集理解起来差不多):
df['A']
2013-01-01 0.543095
2013-01-02 -0.620107
2013-01-03 0.254118
2013-01-04 -1.956330
2013-01-05 -2.726763
2013-01-06 -1.083864
Freq: D, Name: A, dtype: float64
通过 [ ], 对行进行取子集.
df[0:3]
| A | B | C | D | |
|---|---|---|---|---|
| 2013-01-01 | 0.543095 | -0.137837 | 0.919448 | -0.793261 |
| 2013-01-02 | -0.620107 | -0.694901 | 0.126626 | -0.532929 |
| 2013-01-03 | 0.254118 | -0.780577 | -0.446656 | -1.336028 |
df['20130102':'20130104']
| A | B | C | D | |
|---|---|---|---|---|
| 2013-01-02 | -0.620107 | -0.694901 | 0.126626 | -0.532929 |
| 2013-01-03 | 0.254118 | -0.780577 | -0.446656 | -1.336028 |
| 2013-01-04 | -1.956330 | 0.134201 | 0.217032 | -0.883961 |
通过label取子集
可查阅 Selection by Label.
示例:
df.loc[dates[0]]
A 0.543095
B -0.137837
C 0.919448
D -0.793261
Name: 2013-01-01 00:00:00, dtype: float64
df.loc[dates]
| A | B | C | D | |
|---|---|---|---|---|
| 2013-01-01 | 0.543095 | -0.137837 | 0.919448 | -0.793261 |
| 2013-01-02 | -0.620107 | -0.694901 | 0.126626 | -0.532929 |
| 2013-01-03 | 0.254118 | -0.780577 | -0.446656 | -1.336028 |
| 2013-01-04 | -1.956330 | 0.134201 | 0.217032 | -0.883961 |
| 2013-01-05 | -2.726763 | -1.783047 | 0.846121 | 1.874024 |
| 2013-01-06 | -1.083864 | -0.483887 | 0.449576 | -1.337890 |
df.loc[dates[1]]
A -0.620107
B -0.694901
C 0.126626
D -0.532929
Name: 2013-01-02 00:00:00, dtype: float64
df.loc[:, ['A', 'B']]
| A | B | |
|---|---|---|
| 2013-01-01 | 0.543095 | -0.137837 |
| 2013-01-02 | -0.620107 | -0.694901 |
| 2013-01-03 | 0.254118 | -0.780577 |
| 2013-01-04 | -1.956330 | 0.134201 |
| 2013-01-05 | -2.726763 | -1.783047 |
| 2013-01-06 | -1.083864 | -0.483887 |
df.loc['20130102':'20130104', ['A', 'B']]
| A | B | |
|---|---|---|
| 2013-01-02 | -0.620107 | -0.694901 |
| 2013-01-03 | 0.254118 | -0.780577 |
| 2013-01-04 | -1.956330 | 0.134201 |
df.loc['20130102', ['A', 'B']]
A -0.620107
B -0.694901
Name: 2013-01-02 00:00:00, dtype: float64
df.loc[dates[0], 'A']
0.543095059209347
df.at[dates[0], 'A']
0.543095059209347
通过position取子集
示例:
df.iloc[3]
A -1.956330
B 0.134201
C 0.217032
D -0.883961
Name: 2013-01-04 00:00:00, dtype: float64
df.iloc[3:5, 0:2]
| A | B | |
|---|---|---|
| 2013-01-04 | -1.956330 | 0.134201 |
| 2013-01-05 | -2.726763 | -1.783047 |
df.iloc[[1, 2, 4], [0, 2]]
| A | C | |
|---|---|---|
| 2013-01-02 | -0.620107 | 0.126626 |
| 2013-01-03 | 0.254118 | -0.446656 |
| 2013-01-05 | -2.726763 | 0.846121 |
df.iloc[1:3, :]
| A | B | C | D | |
|---|---|---|---|---|
| 2013-01-02 | -0.620107 | -0.694901 | 0.126626 | -0.532929 |
| 2013-01-03 | 0.254118 | -0.780577 | -0.446656 | -1.336028 |
df.iloc[:, 1:3]
| B | C | |
|---|---|---|
| 2013-01-01 | -0.137837 | 0.919448 |
| 2013-01-02 | -0.694901 | 0.126626 |
| 2013-01-03 | -0.780577 | -0.446656 |
| 2013-01-04 | 0.134201 | 0.217032 |
| 2013-01-05 | -1.783047 | 0.846121 |
| 2013-01-06 | -0.483887 | 0.449576 |
df.iloc[1, 1]
-0.6949010999101558
通过逻辑值Boolean indexing取子集
示例:
df[df['A'] > 0]
| A | B | C | D | |
|---|---|---|---|---|
| 2013-01-01 | 0.543095 | -0.137837 | 0.919448 | -0.793261 |
| 2013-01-03 | 0.254118 | -0.780577 | -0.446656 | -1.336028 |
df[df > 0]
| A | B | C | D | |
|---|---|---|---|---|
| 2013-01-01 | 0.543095 | NaN | 0.919448 | NaN |
| 2013-01-02 | NaN | NaN | 0.126626 | NaN |
| 2013-01-03 | 0.254118 | NaN | NaN | NaN |
| 2013-01-04 | NaN | 0.134201 | 0.217032 | NaN |
| 2013-01-05 | NaN | NaN | 0.846121 | 1.874024 |
| 2013-01-06 | NaN | NaN | 0.449576 | NaN |
使用判断函数 isin() 计算后取子集:
df2 = df.copy()
df2['E'] = ['one', 'one', 'two', 'three', 'four', 'three']
df2
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 2013-01-01 | 0.543095 | -0.137837 | 0.919448 | -0.793261 | one |
| 2013-01-02 | -0.620107 | -0.694901 | 0.126626 | -0.532929 | one |
| 2013-01-03 | 0.254118 | -0.780577 | -0.446656 | -1.336028 | two |
| 2013-01-04 | -1.956330 | 0.134201 | 0.217032 | -0.883961 | three |
| 2013-01-05 | -2.726763 | -1.783047 | 0.846121 | 1.874024 | four |
| 2013-01-06 | -1.083864 | -0.483887 | 0.449576 | -1.337890 | three |
df2[df2['E'].isin(['two', 'four'])]
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 2013-01-03 | 0.254118 | -0.780577 | -0.446656 | -1.336028 | two |
| 2013-01-05 | -2.726763 | -1.783047 | 0.846121 | 1.874024 | four |
自定义Setting
Setting a new column automatically aligns the data by the indexes.
s1 = pd.Series([1, 2, 3, 4, 5, 6], index=pd.date_range('20130102', periods=6))
s1
2013-01-02 1
2013-01-03 2
2013-01-04 3
2013-01-05 4
2013-01-06 5
2013-01-07 6
Freq: D, dtype: int64
df['F'] = s1
df.at[dates[0], 'A'] = 0
df.iat[0, 1] = 0
df.loc[:, 'D'] = np.array([5] * len(df))
df
| A | B | C | D | F | |
|---|---|---|---|---|---|
| 2013-01-01 | 0.000000 | 0.000000 | 0.919448 | 5 | NaN |
| 2013-01-02 | -0.620107 | -0.694901 | 0.126626 | 5 | 1.0 |
| 2013-01-03 | 0.254118 | -0.780577 | -0.446656 | 5 | 2.0 |
| 2013-01-04 | -1.956330 | 0.134201 | 0.217032 | 5 | 3.0 |
| 2013-01-05 | -2.726763 | -1.783047 | 0.846121 | 5 | 4.0 |
| 2013-01-06 | -1.083864 | -0.483887 | 0.449576 | 5 | 5.0 |
df2 = df.copy()
df2[df2 > 0] = -df2
df2
| A | B | C | D | F | |
|---|---|---|---|---|---|
| 2013-01-01 | 0.000000 | 0.000000 | -0.919448 | -5 | NaN |
| 2013-01-02 | -0.620107 | -0.694901 | -0.126626 | -5 | -1.0 |
| 2013-01-03 | -0.254118 | -0.780577 | -0.446656 | -5 | -2.0 |
| 2013-01-04 | -1.956330 | -0.134201 | -0.217032 | -5 | -3.0 |
| 2013-01-05 | -2.726763 | -1.783047 | -0.846121 | -5 | -4.0 |
| 2013-01-06 | -1.083864 | -0.483887 | -0.449576 | -5 | -5.0 |
缺失值处理Missing data
pandas 默认用 np.nan 替代缺失值. 默认情况下,它不包括在计算中。可查阅获取更多信息 Missing Data section.
重建索引允许您更改/添加/删除指定轴上的索引。这将返回数据的copy。
df1 = df.reindex(index=dates[0:4], columns=list(df.columns) + ['E'])
df1.loc[dates[0]:dates[1], 'E'] = 1
df1
| A | B | C | D | F | E | |
|---|---|---|---|---|---|---|
| 2013-01-01 | 0.000000 | 0.000000 | 0.919448 | 5 | NaN | 1.0 |
| 2013-01-02 | -0.620107 | -0.694901 | 0.126626 | 5 | 1.0 | 1.0 |
| 2013-01-03 | 0.254118 | -0.780577 | -0.446656 | 5 | 2.0 | NaN |
| 2013-01-04 | -1.956330 | 0.134201 | 0.217032 | 5 | 3.0 | NaN |
df1.dropna(how='any')
| A | B | C | D | F | E | |
|---|---|---|---|---|---|---|
| 2013-01-02 | -0.620107 | -0.694901 | 0.126626 | 5 | 1.0 | 1.0 |
df1.fillna(value=5)
| A | B | C | D | F | E | |
|---|---|---|---|---|---|---|
| 2013-01-01 | 0.000000 | 0.000000 | 0.919448 | 5 | 5.0 | 1.0 |
| 2013-01-02 | -0.620107 | -0.694901 | 0.126626 | 5 | 1.0 | 1.0 |
| 2013-01-03 | 0.254118 | -0.780577 | -0.446656 | 5 | 2.0 | 5.0 |
| 2013-01-04 | -1.956330 | 0.134201 | 0.217032 | 5 | 3.0 | 5.0 |
pd.isna(df1)
| A | B | C | D | F | E | |
|---|---|---|---|---|---|---|
| 2013-01-01 | False | False | False | False | True | False |
| 2013-01-02 | False | False | False | False | False | False |
| 2013-01-03 | False | False | False | False | False | True |
| 2013-01-04 | False | False | False | False | False | True |
对数据进行计算等操作Operations
可查阅 Basic section on Binary Ops.
统计Stats
操作通常会排除丢失的数据。
执行描述性统计:
df.mean()
A -1.022158
B -0.601369
C 0.352025
D 5.000000
F 3.000000
dtype: float64
df.mean(1)
2013-01-01 1.479862
2013-01-02 0.962323
2013-01-03 1.205377
2013-01-04 1.278980
2013-01-05 1.067262
2013-01-06 1.776365
Freq: D, dtype: float64
操作具有不同维度且需要对齐的对象。此外,pandas会自动沿指定的维度进行循环补齐。
s = pd.Series([1, 3, 5, np.nan, 6, 8], index=dates).shift(2)
s
2013-01-01 NaN
2013-01-02 NaN
2013-01-03 1.0
2013-01-04 3.0
2013-01-05 5.0
2013-01-06 NaN
Freq: D, dtype: float64
df.sub(s, axis='index')
| A | B | C | D | F | |
|---|---|---|---|---|---|
| 2013-01-01 | NaN | NaN | NaN | NaN | NaN |
| 2013-01-02 | NaN | NaN | NaN | NaN | NaN |
| 2013-01-03 | -0.745882 | -1.780577 | -1.446656 | 4.0 | 1.0 |
| 2013-01-04 | -4.956330 | -2.865799 | -2.782968 | 2.0 | 0.0 |
| 2013-01-05 | -7.726763 | -6.783047 | -4.153879 | 0.0 | -1.0 |
| 2013-01-06 | NaN | NaN | NaN | NaN | NaN |
Apply函数
Applying functions to the data:
df.apply(np.cumsum)
| A | B | C | D | F | |
|---|---|---|---|---|---|
| 2013-01-01 | 0.000000 | 0.000000 | 0.919448 | 5 | NaN |
| 2013-01-02 | -0.620107 | -0.694901 | 1.046074 | 10 | 1.0 |
| 2013-01-03 | -0.365989 | -1.475479 | 0.599418 | 15 | 3.0 |
| 2013-01-04 | -2.322319 | -1.341277 | 0.816450 | 20 | 6.0 |
| 2013-01-05 | -5.049083 | -3.124324 | 1.662571 | 25 | 10.0 |
| 2013-01-06 | -6.132947 | -3.608212 | 2.112147 | 30 | 15.0 |
df.apply(lambda x: x.max() - x.min())
A 2.980882
B 1.917248
C 1.366104
D 0.000000
F 4.000000
dtype: float64
这里的lambda x就相当于R里面的f(x),不清楚是不是完全一样,查了一下,有很多争论。
Histogramming(柱状)
可查阅 Histogramming and Discretization获取更多。
s = pd.Series(np.random.randint(0, 7, size=10))
s
0 5
1 2
2 1
3 5
4 4
5 0
6 3
7 4
8 6
9 3
dtype: int64
s.value_counts()
5 2
4 2
3 2
6 1
2 1
1 1
0 1
dtype: int64
String Methods(字符串处理)
Series在str属性中配备了一组字符串处理方法,这使得对数组的每个元素的操作都很容易,如下面的代码片段所示。请注意,字符串中模式匹配通常在默认情况下使用正则表达式(在某些情况下总是使用它们)regular expressions by default (and in some cases always uses them)。。有关矢量化字符串方法的更多信息,请参阅 Vectorized String Methods
s = pd.Series(['A', 'B', 'C', 'Aaba', 'Baca', np.nan, 'CABA', 'dog', 'cat'])
s.str.lower()
0 a
1 b
2 c
3 aaba
4 baca
5 NaN
6 caba
7 dog
8 cat
dtype: object
Merge
Concat
pandas有多种方法整合Series 和 DataFrame 对象数据,通过各种set logic for the indexes and relational algebra functionality in the case of join / merge-type operations.
可查阅Merging section获取更多信息.
将pandas对象与contat()连接在一起concat():
df = pd.DataFrame(np.random.randn(10, 4))
df
| 0 | 1 | 2 | 3 | |
|---|---|---|---|---|
| 0 | -0.646039 | -0.491599 | -1.935470 | 0.844283 |
| 1 | 0.740150 | -0.015523 | -1.475191 | 0.768163 |
| 2 | -0.437402 | 0.764390 | 2.144364 | 2.036518 |
| 3 | 0.978963 | 1.098785 | -0.215073 | 0.220535 |
| 4 | -1.464077 | -0.339985 | -0.035533 | 1.845015 |
| 5 | 1.882471 | -0.185556 | -1.137657 | 0.730019 |
| 6 | -0.362014 | 2.269796 | -0.144206 | -0.121095 |
| 7 | -0.267371 | -0.847133 | 0.874015 | -0.965096 |
| 8 | -0.637604 | 0.453296 | -0.218655 | -0.838515 |
| 9 | -0.912365 | 0.085643 | 0.612002 | 0.041122 |
pieces = [df[:3], df[3:7], df[7:]]
pd.concat(pieces)
| 0 | 1 | 2 | 3 | |
|---|---|---|---|---|
| 0 | -0.646039 | -0.491599 | -1.935470 | 0.844283 |
| 1 | 0.740150 | -0.015523 | -1.475191 | 0.768163 |
| 2 | -0.437402 | 0.764390 | 2.144364 | 2.036518 |
| 3 | 0.978963 | 1.098785 | -0.215073 | 0.220535 |
| 4 | -1.464077 | -0.339985 | -0.035533 | 1.845015 |
| 5 | 1.882471 | -0.185556 | -1.137657 | 0.730019 |
| 6 | -0.362014 | 2.269796 | -0.144206 | -0.121095 |
| 7 | -0.267371 | -0.847133 | 0.874015 | -0.965096 |
| 8 | -0.637604 | 0.453296 | -0.218655 | -0.838515 |
| 9 | -0.912365 | 0.085643 | 0.612002 | 0.041122 |
向DataFrame添加列相对较快。但是,添加行需要拷贝,而且可能很费时。我们建议将预先构建的记录列表传递给DataFrame构造函数,而不是通过迭代地将记录追加到DataFrame来构建DataFrame。有关详细信息,请参阅Appending to dataframe。
Join
SQL style merges. See the Database style joining section.
left = pd.DataFrame({'key': ['foo', 'foo'], 'lval': [1, 2]})
right = pd.DataFrame({'key': ['foo', 'foo'], 'rval': [4, 5]})
left
| key | lval | |
|---|---|---|
| 0 | foo | 1 |
| 1 | foo | 2 |
right
| key | rval | |
|---|---|---|
| 0 | foo | 4 |
| 1 | foo | 5 |
pd.merge(left, right, on='key')
| key | lval | rval | |
|---|---|---|---|
| 0 | foo | 1 | 4 |
| 1 | foo | 1 | 5 |
| 2 | foo | 2 | 4 |
| 3 | foo | 2 | 5 |
left = pd.DataFrame({'key': ['foo', 'bar'], 'lval': [1, 2]})
right = pd.DataFrame({'key': ['foo', 'bar'], 'rval': [4, 5]})
left
| key | lval | |
|---|---|---|
| 0 | foo | 1 |
| 1 | bar | 2 |
right
| key | rval | |
|---|---|---|
| 0 | foo | 4 |
| 1 | bar | 5 |
pd.merge(left, right, on='key')
| key | lval | rval | |
|---|---|---|---|
| 0 | foo | 1 | 4 |
| 1 | bar | 2 | 5 |
Grouping
By “group by” we are referring to a process involving one or more of the following steps:
- Splitting the data into groups based on some criteria
- Applying a function to each group independently
- Combining the results into a data structure
更多请查阅 Grouping section.
df = pd.DataFrame({'A': ['foo', 'bar', 'foo', 'bar',
'foo', 'bar', 'foo', 'foo'],
'B': ['one', 'one', 'two', 'three',
'two', 'two', 'one', 'three'],
'C': np.random.randn(8),
'D': np.random.randn(8)})
df
| A | B | C | D | |
|---|---|---|---|---|
| 0 | foo | one | -0.339927 | 1.332559 |
| 1 | bar | one | 1.122698 | 0.145097 |
| 2 | foo | two | -1.115334 | 0.903768 |
| 3 | bar | three | 0.657891 | 0.225078 |
| 4 | foo | two | 1.251910 | 0.104768 |
| 5 | bar | two | 0.133649 | 0.580325 |
| 6 | foo | one | 0.722858 | -0.673479 |
| 7 | foo | three | 0.481918 | 0.066882 |
df.groupby('A').sum()
| C | D | |
|---|---|---|
| A | ||
| --- | --- | --- |
| bar | 1.914237 | 0.950501 |
| foo | 1.001426 | 1.734498 |
df.groupby(['A', 'B']).sum()
| C | D | ||
|---|---|---|---|
| A | B | ||
| --- | --- | --- | --- |
| bar | one | 1.122698 | 0.145097 |
| three | 0.657891 | 0.225078 | |
| two | 0.133649 | 0.580325 | |
| foo | one | 0.382931 | 0.659080 |
| three | 0.481918 | 0.066882 | |
| two | 0.136577 | 1.008536 |
Reshaping
这部分内容就像R里面的长变扁的操作(spread-gather)更多请查阅 Hierarchical Indexing and Reshaping.
Stack
tuples = list(zip(*[['bar', 'bar', 'baz', 'baz',
'foo', 'foo', 'qux', 'qux'],
['one', 'two', 'one', 'two',
'one', 'two', 'one', 'two']]))
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
df = pd.DataFrame(np.random.randn(8, 2), index=index, columns=['A', 'B'])
df2 = df[:4]
df2
| A | B | ||
|---|---|---|---|
| first | second | ||
| --- | --- | --- | --- |
| bar | one | -2.130131 | 0.285138 |
| two | -0.110862 | -0.878289 | |
| baz | one | 0.134119 | 1.615108 |
| two | -1.913324 | 0.093240 |
stacked = df2.stack()
stacked
first second
bar one A -2.130131
B 0.285138
two A -0.110862
B -0.878289
baz one A 0.134119
B 1.615108
two A -1.913324
B 0.093240
dtype: float64
stacked.unstack()
| A | B | ||
|---|---|---|---|
| first | second | ||
| --- | --- | --- | --- |
| bar | one | -2.130131 | 0.285138 |
| two | -0.110862 | -0.878289 | |
| baz | one | 0.134119 | 1.615108 |
| two | -1.913324 | 0.093240 |
stacked.unstack(1)
| second | one | two | |
|---|---|---|---|
| first | |||
| --- | --- | --- | --- |
| bar | A | -2.130131 | -0.110862 |
| B | 0.285138 | -0.878289 | --- |
| baz | A | 0.134119 | -1.913324 |
| B | 1.615108 | 0.093240 | --- |
stacked.unstack(0)
| first | bar | baz | |
|---|---|---|---|
| second | |||
| --- | --- | --- | --- |
| one | A | -2.130131 | 0.134119 |
| B | 0.285138 | 1.615108 | |
| two | A | -0.110862 | -1.913324 |
| B | -0.878289 | 0.093240 |
Pivot tables
更多请查阅 Pivot Tables.
df = pd.DataFrame({'A': ['one', 'one', 'two', 'three'] * 3,
'B': ['A', 'B', 'C'] * 4,
'C': ['foo', 'foo', 'foo', 'bar', 'bar', 'bar'] * 2,
'D': np.random.randn(12),
'E': np.random.randn(12)})
df
| A | B | C | D | E | |
|---|---|---|---|---|---|
| 0 | one | A | foo | -0.490779 | -0.537540 |
| 1 | one | B | foo | -0.889396 | -0.602550 |
| 2 | two | C | foo | -1.244254 | 0.006629 |
| 3 | three | A | bar | 0.215834 | 1.251794 |
| 4 | one | B | bar | -0.374261 | -0.210549 |
| 5 | one | C | bar | -1.660775 | 0.140967 |
| 6 | two | A | foo | 1.216161 | 0.614097 |
| 7 | three | B | foo | -0.200877 | 2.106850 |
| 8 | one | C | foo | 0.501083 | -0.814486 |
| 9 | one | A | bar | 0.945288 | 0.140742 |
| 10 | two | B | bar | 0.121520 | -0.256242 |
| 11 | three | C | bar | 2.781746 | 0.739417 |
pd.pivot_table(df, values='D', index=['A', 'B'], columns=['C'])
| C | bar | foo | |
|---|---|---|---|
| A | B | ||
| --- | --- | --- | --- |
| one | A | 0.945288 | -0.490779 |
| B | -0.374261 | -0.889396 | |
| C | -1.660775 | 0.501083 | |
| three | A | 0.215834 | NaN |
| B | NaN | -0.200877 | |
| C | 2.781746 | NaN | |
| two | A | NaN | 1.216161 |
| B | 0.121520 | NaN | |
| C | NaN | -1.244254 |
Time series时间序列
pandas具有简单、强大和高效的功能,用于在频率转换期间执行重采样操作(例如,将第二次数据转换为5分钟的数据)。这在(但不限于)金融应用程序中非常常见。更多请查阅 Time Series section.
rng = pd.date_range('1/1/2012', periods=100, freq='S')
ts = pd.Series(np.random.randint(0, 500, len(rng)), index=rng)
ts.resample('5Min').sum()
2012-01-01 22619
Freq: 5T, dtype: int64
rng = pd.date_range('3/6/2012 00:00', periods=5, freq='D')
ts = pd.Series(np.random.randn(len(rng)), rng)
ts
2012-03-06 0.803411
2012-03-07 0.185685
2012-03-08 2.076735
2012-03-09 -0.351221
2012-03-10 -0.523163
Freq: D, dtype: float64
ts_utc = ts.tz_localize('UTC')
ts_utc
2012-03-06 00:00:00+00:00 0.803411
2012-03-07 00:00:00+00:00 0.185685
2012-03-08 00:00:00+00:00 2.076735
2012-03-09 00:00:00+00:00 -0.351221
2012-03-10 00:00:00+00:00 -0.523163
Freq: D, dtype: float64
#Converting to another time zone:
ts_utc.tz_convert('US/Eastern')
2012-03-05 19:00:00-05:00 0.803411
2012-03-06 19:00:00-05:00 0.185685
2012-03-07 19:00:00-05:00 2.076735
2012-03-08 19:00:00-05:00 -0.351221
2012-03-09 19:00:00-05:00 -0.523163
Freq: D, dtype: float64
#Converting between time span representations:
rng = pd.date_range('1/1/2012', periods=5, freq='M')
ts = pd.Series(np.random.randn(len(rng)), index=rng)
ts
2012-01-31 0.449247
2012-02-29 -0.965564
2012-03-31 -1.155146
2012-04-30 0.015175
2012-05-31 0.218811
Freq: M, dtype: float64
ps = ts.to_period()
ps
2012-01 0.449247
2012-02 -0.965564
2012-03 -1.155146
2012-04 0.015175
2012-05 0.218811
Freq: M, dtype: float64
ps.to_timestamp()
2012-01-01 0.449247
2012-02-01 -0.965564
2012-03-01 -1.155146
2012-04-01 0.015175
2012-05-01 0.218811
Freq: MS, dtype: float64
在 period和timestamp之间进行转换可以使用一些方便的算术函数。在下面的示例中,我们将年度结束时间为11月份的季度频率转换为季度结束后下一个月的上午9点:
prng = pd.period_range('1990Q1', '2000Q4', freq='Q-NOV')
ts = pd.Series(np.random.randn(len(prng)), prng)
ts.index = (prng.asfreq('M', 'e') + 1).asfreq('H', 's') + 9
ts.head()
1990-03-01 09:00 1.807079
1990-06-01 09:00 0.786039
1990-09-01 09:00 -0.787752
1990-12-01 09:00 0.674390
1991-03-01 09:00 -0.615256
Freq: H, dtype: float64
Categoricals分类数据
这小节介绍数据类型转换,pandas可以在DataFrame中包含分类数据。有关完整文档,请参阅 分类介绍 和 API文档.
df = pd.DataFrame({"id": [1, 2, 3, 4, 5, 6],
"raw_grade": ['a', 'b', 'b', 'a', 'a', 'e']})
df["grade"] = df["raw_grade"].astype("category")
df["grade"]
0 a
1 b
2 b
3 a
4 a
5 e
Name: grade, dtype: category
Categories (3, object): [a, b, e]
df["grade"].cat.categories = ["very good", "good", "very bad"]
df["grade"] = df["grade"].cat.set_categories(["very bad", "bad", "medium",
"good", "very good"])
df["grade"]
0 very good
1 good
2 good
3 very good
4 very good
5 very bad
Name: grade, dtype: category
Categories (5, object): [very bad, bad, medium, good, very good]
df.sort_values(by="grade")
| id | raw_grade | grade | |
|---|---|---|---|
| 5 | 6 | e | very bad |
| 1 | 2 | b | good |
| 2 | 3 | b | good |
| 0 | 1 | a | very good |
| 3 | 4 | a | very good |
| 4 | 5 | a | very good |
df.groupby("grade").size()
grade
very bad 1
bad 0
medium 0
good 2
very good 3
dtype: int64
绘图Plotting
更多请查阅 Plotting docs.
我们使用标准约定引用matplotlib API:
import matplotlib.pyplot as plt
plt.close('all')
ts = pd.Series(np.random.randn(1000),
index=pd.date_range('1/1/2000', periods=1000))
ts = ts.cumsum()
ts.plot()
<matplotlib.axes._subplots.AxesSubplot at 0x113d57130>

df = pd.DataFrame(np.random.randn(1000, 4), index=ts.index,
columns=['A', 'B', 'C', 'D'])
df = df.cumsum()
plt.figure()
df.plot()
<matplotlib.axes._subplots.AxesSubplot at 0x113a18a30>

#plt.legend(loc='best')
数据读入,导出
CSV
df.to_csv('foo.csv')
pd.read_csv('foo.csv')
| Unnamed: 0 | A | B | C | D | |
|---|---|---|---|---|---|
| 0 | 2000-01-01 | 0.630907 | 0.805600 | -0.855205 | -0.985009 |
| 1 | 2000-01-02 | 1.391750 | 0.429901 | -1.942345 | -0.477537 |
| 2 | 2000-01-03 | 1.269755 | 0.198534 | -0.644477 | 0.335111 |
| 3 | 2000-01-04 | 0.856252 | 0.730361 | -0.147301 | -0.266914 |
| 4 | 2000-01-05 | -0.616704 | 0.734190 | 1.521054 | 0.939565 |
| ... | ... | ... | ... | ... | ... |
| 995 | 2002-09-22 | -7.751938 | 14.573749 | -18.099185 | -0.835212 |
| 996 | 2002-09-23 | -8.905303 | 15.380542 | -17.407252 | -0.307603 |
| 997 | 2002-09-24 | -7.086500 | 14.886025 | -18.516197 | 0.144851 |
| 998 | 2002-09-25 | -6.786619 | 14.331656 | -18.722913 | 1.900055 |
| 999 | 2002-09-26 | -6.201188 | 14.861311 | -18.462743 | 1.800434 |
1000 rows × 5 columns
HDF5格式
Reading and writing to HDFStores.
Writing to a HDF5 Store.
import tablesimport openpyxldf.to_hdf('foo.h5', 'df')
生成后可在当前工作目录下生成文件,可用ls查看:
ls
foo.csv foo.h5 �[31mquantstats.ipynb�[m�[m*
Excel
Reading and writing to MS Excel.
Writing to an excel file.
df.to_excel('foo.xlsx', sheet_name='Sheet1')
了解(Gotchas)
如果您正在尝试执行操作,您可能会看到类似于以下内容的异常:
if pd.Series([False, True, False]):
print("I was true")
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-130-5c782b38cd2f> in <module>
----> 1 if pd.Series([False, True, False]):
2 print("I was true")
/Library/Frameworks/Python.framework/Versions/3.8/lib/python3.8/site-packages/pandas/core/generic.py in __nonzero__(self)
1476
1477 def __nonzero__(self):
-> 1478 raise ValueError(
1479 f"The truth value of a {type(self).__name__} is ambiguous. "
1480 "Use a.empty, a.bool(), a.item(), a.any() or a.all()."
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
参考学习资料:
https://pandas.pydata.org/pandas-docs/stable/getting_started/10min.html#selection