一、Series和DataFrame
1. pandas.Series
2. pandas.DataFrame
二、Pandas常见用法
1. 访问数据
1.1 head()和tail()
1.2 describe()
1.3 T
1.4 sort_values()
1.5 nlargest()
1.6 sample()
2. 选择数据
标签选择-toc" style="margin-left:80px;">2.1 根据标签选择
2.2 根据位置选择
2.3 布尔索引
3. 处理缺失值
3.1 dropna()
3.2 fillna()
4. 操作方法
4.1 agg()
4.2 apply()
4.3 value_counts()
4.4 str
5. 合并
5.1 concat()
5.2 merge()
6. 分组GroupBy
6.1 单列分组
6.2 多列分组
6.3 采用多聚合法
6.4 不同列的聚合统计不同
6.5 更多
三、Pandas 进阶用法
1. reshape
1.1 stack() 和 unstack()
1.2 pivot_table()
2. 时间序列
3. 分类
4. IO
一、Series和DataFrame
Pandas特别适合处理表格数据,如SQL表格、EXCEL表格。时间序列有序或无序。任何具有行和列标签的矩阵数据。
打开Jupyter Notebook,导入numpy和pandas开始我们的教程:
importnumpyasnp importpandasaspd
1. pandas.Series
pd.Series([1,3,5,np.nan,6,8])
输出:
01.0 13.0 25.0 3NaN 46.0 58.0 dtype:float64
默认索引值为0、1、2、3、4、5。index
属性,指定为‘c','a','i','yong','j','i'。
pd.Series([1,3,5,np.nan,6,8],index=['c','a','i','yong','j','i'])
输出如下,我们可以看到index可重复。
c1.0 a3.0 i5.0 yongNaN j&nsp; 6.0
i 8.0
dtype: float64
2. pandas.DataFrame
pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), index=['i','ii','iii'], columns=['A', 'B', 'C'])
输出表格如下,。
A | B | C | |
---|---|---|---|
i | 1 | 2 | 3 |
ii | 4 | 5 | 6 |
iii | 7 | 8 | 9 |
二、Pandas常见用法
1. 访问数据
准备数据,随机生成6行4列的二维数组,行标签为从20210101到20210106的日期,列标签为A、B、C、D。
import numpy as np
import pandas as pd
np.random.seed(20201212)
df = pd.DataFrame(np.random.randn(6, 4), index=pd.date_range('20210101', periods=6), columns=list('ABCD'))
df
记住的用法。
展示表格如下:
A | B | C | D | |
---|---|---|---|---|
2021-01-01 | 0.270961 | -0.405463 | 0.348373 | 0.828572 |
2021-01-02 | 0.696541 | 0.136352 | -1.64592 | -0.69841 |
2021-01-03 | 0.325415 | -0.602236 | -0.134508 | 1.28121 |
2021-01-04 | -0.33032 | -1.40384 | -0.93809 | 1.48804 |
2021-01-05 | 0.348708 | 1.27175 | 0.626011 | -0.253845 |
2021-01-06 | -0.816064 | 1.30197 | 0.656281 | -1.2718 |
1.1 head()和tail()
:
df.head(2)
展示表格如下:
A | B | C | D | |
---|---|---|---|---|
2021-01-01 | 0.270961 | -0.405463 | 0.348373 | 0.828572 |
2021-01-02 | 0.696541 | 0.136352 | -1.64592 | -0.69841 |
df.tail(3)
展示表格如下:
A | B | C | D | |
---|---|---|---|---|
2021-01-04 | -0.33032 | -1.40384 | -0.93809 | 1.48804 |
2021-01-05 | 0.348708 | 1.27175 | 0.626011 | -0.253845 |
2021-01-06 | -0.816064 | 1.30197 | 0.656281 | -1.2718 |
1.2 describe()
df.describe()
展示如下:
A | B | C | D | |
---|---|---|---|---|
count | 6 | 6 | 6 | 6 |
mean | 0.0825402 | 0.0497552 | -0.181309 | 0.22896 |
std | 0.551412 | 1.07834 | 0.933155 | 1.13114 |
min | -0.816064 | -1.40384 | -1.64592 | -1.2718 |
25% | -0.18 | -0.553043 | -0.737194 | -0.587269 |
50% | 0.298188 | -0.134555 | 0.106933 | 0.287363 |
75% | 0.342885 | 0.987901 | 0.556601 | 1.16805 |
max | 0.696541 | 1.30197 | 0.656281 | 1.48804 |
我们首先回顾一下我们掌握的数学公式。
:
:
:
我们解释一下pandas的describe统计信息各属性的意义。我们仅以 A
列为例。
-
25%
表示四分之一分位数。A列的四分之一分位数为-0.18。即,25%的数据比-0.18小。 -
50%
表示二分之一分位数。A列的四分之一分位数为0.298188。即,50%的数据比0.298188小。 -
75%
表示四分之三分位数。A列的四分之三分位数为0.342885。即,75%的数据比0.342885小。 -
max
表示最大值。A列的最大值为0.696541。即,100%的数据比0.696541小。
1.3 T
df.T
展示表格如下:
2021-01-01 | 2021-01-02 | 2021-01-03 | 2021-01-04 | 2021-01-05 | 2021-01-06 | |
---|---|---|---|---|---|---|
A | 0.270961 | 0.696541 | 0.325415 | -0.33032 | 0.348708 | -0.816064 |
B | -0.405463 | 0.136352 | -0.602236 | -1.40384 | 1.27175 | 1.30197 |
C | 0.348373 | -1.64592 | -0.134508 | -0.93809 | 0.626011 | 0.656281 |
D | 0.828572 | -0.69841 | 1.28121 | 1.48804 | -0.253845 | -1.2718 |
1.4 sort_values()
df.sort_values(by='C')
展示表格如下:
A | B | C | D | |
---|---|---|---|---|
2021-01-02 | 0.696541 | 0.136352 | -1.64592 | -0.69841 |
2021-01-04 | -0.33032 | -1.40384 | -0.93809 | 1.48804 |
2021-01-03 | 0.325415 | -0.602236 | -0.134508 | 1.28121 |
2021-01-01 | 0.270961 | -0.405463 | 0.348373 | 0.828572 |
2021-01-05 | 0.348708 | 1.27175 | 0.626011 | -0.253845 |
2021-01-06 | -0.816064 | 1.30197 | 0.656281 | -1.2718 |
1.5 nlargest()
df.nlargest(2,'A')
展示表格如下:
A | B | C | D | |
---|---|---|---|---|
2021-01-02 | 0.696541 | 0.136352 | -1.64592 | -0.69841 |
2021-01-05 | 0.348708 | 1.27175 | 0.626011 | -0.253845 |
1.6 sample()
df.sample(5)
df.sample(frac=0.01)
2. 选择数据
2.1 根据标签选择
我们输入df['A']
命令选取A列。
df['A']
输出A列数据,同时也是一个Series对象:
2021-01-01 0.270961
2021-01-02 0.696541
2021-01-03 0.325415
2021-01-04 -0.330320
2021-01-05 0.348708
2021-01-06 -0.816064
Name: A, dtype: float64
df[0:3]
该代码与df.head(3)
同理。但df[0:3]
是NumPy的数组选择方式,这说明了Pandas对于NumPy具有良好的支持。
df[0:3]
展示表格如下:
A | B | C | D | |
---|---|---|---|---|
2021-01-01 | 0.270961 | -0.405463 | 0.348373 | 0.828572 |
2021-01-02 | 0.696541 | 0.136352 | -1.64592 | -0.69841 |
2021-01-03 | 0.325415 | -0.602236 | -0.134508 | 1.28121 |
df.loc['2021-01-01':'2021-01-02', ['A', 'B']]
展示表格如下:
A | B | |
---|---|---|
2021-01-01 | 0.270961 | -0.405463 |
2021-01-02 | 0.696541 | 0.136352 |
2.2 根据位置选择
df.iloc[3:5, 0:3]
A | B | C | |
---|---|---|---|
2021-01-04 | -0.33032 | -1.40384 | -0.93809 |
2021-01-05 | 0.348708 | 1.27175 | 0.626011 |
df.iloc[:, 1:3]
B | C | |
---|---|---|
2021-01-01 | -0.405463 | 0.348373 |
2021-01-02 | 0.136352 | -1.64592 |
2021-01-03 | -0.602236 | -0.134508 |
2021-01-04 | -1.40384 | -0.93809 |
2021-01-05 | 1.27175 | 0.626011 |
2021-01-06 | 1.30197 | 0.656281 |
2.3 布尔索引
DataFrame可根据条件进行筛选,当条件判断True
时,返回。当条件判断为False
时,过滤掉。
filter = df['A'] > 0
filter
输出结果如下,可以看到2021-01-04
和2021-01-06
的行为False。
2021-01-01 True
2021-01-02 True
2021-01-03 True
2021-01-04 False
2021-01-05 True
2021-01-06 False
Name: A, dtype: bool
我们通过过滤器查看数据集。
df[filter]
# df[df['A'] > 0]
查看表格我们可以发现,2021-01-04
和2021-01-06
的行被过滤掉了。
A | B | C | D | |
---|---|---|---|---|
2021-01-01 | 0.270961 | -0.405463 | 0.348373 | 0.828572 |
2021-01-02 | 0.696541 | 0.136352 | -1.64592 | -0.69841 |
2021-01-03 | 0.325415 | -0.602236 | -0.134508 | 1.28121 |
2021-01-05 | 0.348708 | 1.27175 | 0.626011 | -0.253845 |
3. 处理缺失值
准备数据。
DataFrame添加一列
df3=df.copy()
df3.loc[:3,'E']=1.0
#f_series={'2021-01-02':1.0,'2021-01-03':2.0,'2021-01-04':3.0,'2021-01-05':4.0,'2021-01-06':5.0}
f_series=[9.0,1.0,2.0,3.0,4.0,5.0]
#df3['F']=pd.Series(f_series)
df3["F"] = ([0,1.0,2.0,3.0,4.0,5.0])
print(df3)
展示表格如下:
A | B | C | D | F | E | |
---|---|---|---|---|---|---|
2021-01-01 | 0.270961 | -0.405463 | 0.348373 | 0.828572 | nan | 1 |
2021-01-02 | 0.696541 | 0.136352 | -1.64592 | -0.69841 | 1 | 1 |
2021-01-03 | 0.325415 | -0.602236 | -0.134508 | 1.28121 | 2 | 1 |
2021-01-04 | -0.33032 | -1.40384 | -0.93809 | 1.48804 | 3 | nan |
2021-01-05 | 0.348708 | 1.27175 | 0.626011 | -0.253845 | 4 | nan |
2021-01-06 | -0.816064 | 1.30197 | 0.656281 | -1.2718 | 5 | nan |
3.1 dropna()
df2.dropna(how='any')
A | B | C | D | F | E | |
---|---|---|---|---|---|---|
2021-01-02 | 0.696541 | 0.136352 | -1.64592 | -0.69841 | 1 | 1 |
2021-01-03 | 0.325415 | -0.602236 | -0.134508 | 1.28121 | 2 | 1 |
3.2 fillna()
使用filna命令填补NaN值。
df2.fillna(df2.mean())
。
展示表格如下:
A | B | C | D | F | E | |
---|---|---|---|---|---|---|
2021-01-01 | 0.270961 | -0.405463 | 0.348373 | 0.828572 | 3 | 1 |
2021-01-02 | 0.696541 | 0.136352 | -1.64592 | -0.69841 | 1 | 1 |
2021-01-03 | 0.325415 | -0.602236 | -0.134508 | 1.28121 | 2 | 1 |
2021-01-04 | -0.33032 | -1.40384 | -0.93809 | 1.48804 | 3 | 1 |
2021-01-05 | 0.348708 | 1.27175 | 0.626011 | -0.253845 | 4 | 1 |
2021-01-06 | -0.816064 | 1.30197 | 0.656281 | -1.2718 | 5 | 1 |
4. 操作方法
4.1 agg()
agg是Aggregate的缩写,意为聚合。
常用聚合方法如下:
df.mean()
A 0.082540
B 0.049755
C -0.181309
D 0.228960
dtype: float64
df.mean(axis=1)
输出:
2021-01-01 0.260611
2021-01-02 -0.377860
2021-01-03 0.217470
2021-01-04 -0.296053
2021-01-05 0.498156
2021-01-06 -0.032404
dtype: float64
如果我们想查看某一列的多项聚合统计怎么办?
df.agg(['std','mean'])['A']
返回结果显示标准差std和均值mean:
std 0.551412
mean 0.082540
Name: A, dtype: float64
:
df.agg({'A':['max','mean'],'B':['mean','std','var']})
返回结果如下:
A | B | |
---|---|---|
max | 0.696541 | nan |
mean | 0.0825402 | 0.0497552 |
std | nan | 1.07834 |
var | nan | 1.16281 |
4.2 apply()
df.apply(np.sum)
输出结果为:
A 0.495241
B 0.298531
C -1.087857
D 1.373762
dtype: float64
apply方法支持lambda表达式。
df.apply(lambda n: n*2)
A | B | C | D | |
---|---|---|---|---|
2021-01-01 | 0.541923 | -0.810925 | 0.696747 | 1.65714 |
2021-01-02 | 1.39308 | 0.272704 | -3.29185 | -1.39682 |
2021-01-03 | 0.65083 | -1.20447 | -0.269016 | 2.56242 |
2021-01-04 | -0.66064 | -2.80768 | -1.87618 | 2.97607 |
2021-01-05 | 0.697417 | 2.5435 | 1.25202 | -0.50769 |
2021-01-06 | -1.63213 | 2.60393 | 1.31256 | -2.5436 |
4.3 value_counts()
我们重新生成一些整数数据,来保证有一定的数据重复。
np.random.seed(101)
df3 = pd.DataFrame(np.random.randint(0,9,size = (6,4)),columns=list('ABCD'))
df3
A | B | C | D | |
---|---|---|---|---|
0 | 1 | 6 | 7 | 8 |
1 | 4 | 8 | 5 | 0 |
2 | 5 | 8 | 1 | 3 |
3 | 8 | 3 | 3 | 2 |
4 | 8 | 3 | 7 | 0 |
5 | 7 | 8 | 4 | 3 |
df3['A'].value_counts()
查看输出我们可以看到 A列的数字8有两个,其他数字的数量为1。
8 2
7 1
5 1
4 1
1 1
Name: A, dtype: int64
4.4 str
Pandas内置字符串处理方法。
names = pd.Series(['andrew','bobo','claire','david','4'])
names.str.upper()
通过以上代码我们将
0 ANDREW
1 BOBO
2 CLAIRE
3 DAVID
4 4
dtype: object
names.str.capitalize()
输出为:
0 Andrew
1 Bobo
2 Claire
3 David
4 4
dtype: object
names.str.isdigit()
输出为:
0 False
1 False
2 False
3 False
4 True
dtype: bool
tech_finance = ['GOOG,APPL,AMZN','JPM,BAC,GS']
tickers = pd.Series(tech_finance)
tickers.str.split(',').str[0:2]
以逗号分割字符串,结果为:
0 [GOOG, APPL]
1 [JPM, BAC]
dtype: object
5. 合并
5.1 concat()
concat用来将数据集串联起来。我们先准备数据。
data_one = {'Col1': ['A0', 'A1', 'A2', 'A3'],'Col2': ['B0', 'B1', 'B2', 'B3']}
data_two = {'Col1': ['C0', 'C1', 'C2', 'C3'], 'Col2': ['D0', 'D1', 'D2', 'D3']}
one = pd.DataFrame(data_one)
two = pd.DataFrame(data_two)
print(pd.concat([one,two]))
得到表格:
Col1 | Col2 | |
---|---|---|
0 | A0 | B0 |
1 | A1 | B1 |
2 | A2 | B2 |
3 | A3 | B3 |
0 | C0 | D0 |
1 | C1 | D1 |
2 | C2 | D2 |
3 | C3 | D3 |
5.2 merge()
registrations = pd.DataFrame({'reg_id':[1,2,3,4],'name':['Andrew','Bobo','Claire','David']})
logins = pd.DataFrame({'log_id':[1,2,3,4],'name':['Xavier','Andrew','Yolanda','Bobo']})
我们根据name
来连接两个张表,连接方式为outer
。
pd.merge(left=registrations, right=logins, how='outer',on='name')
返回结果为:
reg_id | name | log_id | |
---|---|---|---|
0 | 1 | Andrew | 2 |
1 | 2 | Bobo | 4 |
2 | 3 | Claire | nan |
3 | 4 | David | nan |
4 | nan | Xavier | 1 |
5 | nan | Yolanda | 3 |
我们注意, 有4种连接方式。
表示是否选取左右两侧表的nan值。如left表示保留左侧表中所有数据,
当遇到右侧表数据为nan值时,不显示右侧的数据。简单来说,把left表和right表看作两个集合。
6. 分组GroupBy
Pandas中的分组功能非常类似于SQL语句SELECT Column1, Column2, mean(Column3),
sum(Column4)FROM SomeTableGROUP BY Column1, Column2
。
即使没有接触过SQL也没有关系,分组就相当于把表格数据按照某一列进行拆分、统计、合并的过程。
准备数据。
np.random.seed(20201212)
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列有很多重复数据。这时我们可以根据foo/bar或者one/two进行分组。
A | B | C | D | |
---|---|---|---|---|
0 | foo | one | 0.270961 | 0.325415 |
1 | bar | one | -0.405463 | -0.602236 |
2 | foo | two | 0.348373 | -0.134508 |
3 | bar | three | 0.828572 | 1.28121 |
4 | foo | two | 0.696541 | -0.33032 |
5 | bar | two | 0.136352 | -1.40384 |
6 | foo | one | -1.64592 | -0.93809 |
7 | foo | three | -0.69841 | 1.48804 |
6.1 单列分组
df.groupby('A')
执行上方代码可以看到,groupby方法返回的是一个类型为DataFrameGroupBy
的对象。我们无法直接查看,需要应用聚合函数。参考本文4.1节。
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x0000014C6742E248>
。
df.groupby('A').sum()
展示表格如下:
A | C | D |
---|---|---|
bar | 0.559461 | -0.724868 |
foo | -1.02846 | 0.410533 |
6.2 多列分组
df.groupby(['A', 'B']).sum()
分组后显示结果如下:
A | B | C | D |
---|---|---|---|
bar | one | -0.405463 | -0.602236 |
one | -0.405463 | -0.602236 | |
three | 0.828572 | 1.28121 | |
two | 0.136352 | -1.40384 | |
foo | one | -1.37496 | -0.612675 |
three | -0.69841 | 1.48804 | |
two | 1.04491 | -0.464828 |
6.3 应用多聚合方法
下方代码根据A分类且只统计C
列的数值。
df.groupby('A')['C'].agg([np.sum, np.mean, np.std])
可以看到bar组与foo组各聚合函数的结果如下:
A | sum | mean | std |
---|---|---|---|
bar | 0.559461 | 0.186487 | 0.618543 |
foo | -1.02846 | -0.205692 | 0.957242 |
6.4 不同列进行不同聚合统计
下方代码对C、D列分别进行不同的聚合统计,对C列进行求和,对D列进行标准差统计。
df.groupby('A').agg({'C': 'sum', 'D': lambda x: np.std(x, ddof=1)})
输出如下:
A | C | D |
---|---|---|
bar | 0.559461 | 1.37837 |
foo | -1.02846 | 0.907422 |
6.5 更多
更多关于Pandas的goupby
方法请参考官网: Pandas User Guide - groupby
Pandas User Guide - groupby: https://pandas.pydata.org/pandas-docs/stable/user_guide/groupby.html](https://pandas.pydata.org/pandas-docs/stable/user_guide/groupby.html
三、Pandas 进阶用法
1. reshape
对于复杂表格,我们需要将其转换成适合我们理解的样子,比如根据某些属性分组后进行单独统计。
1.1 stack() 和 unstack()
准备数据。
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'])
根据上方代码,我们创建了一个复合索引。
MultiIndex([('bar', 'one'),
('bar', 'two'),
('baz', 'one'),
('baz', 'two'),
('foo', 'one'),
('foo', 'two'),
('qux', 'one'),
('qux', 'two')],
names=['first', 'second'])
我们创建一个具备复合索引的DataFrame。
np.random.seed(20201212)
df = pd.DataFrame(np.random.randn(8, 2), index=index, columns=['A', 'B'])
df
输出如下:
A | B | C | D |
---|---|---|---|
bar | one | 0.270961 | -0.405463 |
two | 0.348373 | 0.828572 | |
baz | one | 0.696541 | 0.136352 |
two | -1.64592 | -0.69841 | |
foo | one | 0.325415 | -0.602236 |
two | -0.134508 | 1.28121 | |
qux | one | -0.33032 | -1.40384 |
two | -0.93809 | 1.48804 |
我们执行stack
方法。
stacked = df.stack()
stacked
输出堆叠(压缩)后的表格如下。注意:你使用Jupyter Notebook/Lab进行的输出可能和如下结果不太一样。下方输出的各位为了方便在Markdown中显示有一定的调整。
first second
bar one A &nb