第二章 Pandas基础
文章目录
2.1 文件的读取和写入
2.1.1 文件读取
pandas
可以读取的文件格式有很多,主要介绍读取csv, excel, txt
文件
- 公共参数介绍
header=None
表示第一行不作为列名index_col
表示把某一列或几列作为索引usecols
表示读取列的集合,默认读取所有的列parse_dates
表示需要转化为时间的列nrows
表示读取的数据行数
In [10]: pd.read_table('data/my_table.txt', header=None)
Out[10]:
0 1 2 3
0 col1 col2 col3 col4
1 2 a 1.4 apple 2020/1/1
2 3 b 3.4 banana 2020/1/2
3 6 c 2.5 orange 2020/1/5
4 5 d 3.2 lemon 2020/1/7
In [11]: pd.read_csv('data/my_csv.csv', index_col=['col1', 'col2'])
Out[11]:
col3 col4 col5
col1 col2
2 a 1.4 apple 2020/1/1
3 b 3.4 banana 2020/1/2
6 c 2.5 orange 2020/1/5
5 d 3.2 lemon 2020/1/7
In [12]: pd.read_table('data/my_table.txt', usecols=['col1', 'col2'])
Out[12]:
col1 col2
0 2 a
1 3 b
2 6 c
3 5 d
In [13]: pd.read_csv('data/my_csv.csv', parse_dates=['col5'])
Out[13]:
col1 col2 col3 col4 col5
0 2 a 1.4 apple 2020-01-01
1 3 b 3.4 banana 2020-01-02
2 6 c 2.5 orange 2020-01-05
3 5 d 3.2 lemon 2020-01-07
In [14]: pd.read_excel('data/my_excel.xlsx', nrows=2)
Out[14]:
col1 col2 col3 col4 col5
0 2 a 1.4 apple 2020/1/1
1 3 b 3.4 banana 2020/1/2
- 分隔符问题
-
读取
txt
文件时,经常遇到分隔符非空格的情况,read_table
有一个分割参数sep
,它使得用户可以自定义分割符号,进行txt
数据的读取 -
使用前
In [15]: pd.read_table('data/my_table_special_sep.txt')
Out[15]:
col1 |||| col2
0 TS |||| This is an apple.
1 GQ |||| My name is Bob.
2 WT |||| Well done!
3 PT |||| May I help you?
- 使用后
In [16]: pd.read_table('data/my_table_special_sep.txt',
....: sep=' \|\|\|\| ', engine='python')
....:
Out[16]:
col1 col2
0 TS This is an apple.
1 GQ My name is Bob.
2 WT Well done!
3 PT May I help you?
- 使用
read_table
的时注意,参数sep
中使用的是正则表达式,因此需要对|
进行转义变成\|
,否则无法读取到正确的结果
2.1.2 数据写入
- 在数据写入中,最常用的操作是把
index
设置为False
- 特别当索引没有特殊意义的时候,这样的行为能把索引在保存的时候去除
In [17]: df_csv.to_csv('data/my_csv_saved.csv', index=False)
In [18]: df_excel.to_excel('data/my_excel_saved.xlsx', index=False)
pandas
中没有定义to_table
函数,但是to_csv
可以保存为txt
文件
- 允许自定义分隔符,常用制表符
\t
分割
In [19]: df_txt.to_csv('data/my_txt_saved.txt', sep='\t', index=False)
- 将表格快速转为
markdown
和latex
语言,使用to_markdown
和to_latex
函数
- 需要安装
tabulate
包
In [20]: print(df_csv.to_markdown())
| | col1 | col2 | col3 | col4 | col5 |
|---:|-------:|:-------|-------:|:-------|:---------|
| 0 | 2 | a | 1.4 | apple | 2020/1/1 |
| 1 | 3 | b | 3.4 | banana | 2020/1/2 |
| 2 | 6 | c | 2.5 | orange | 2020/1/5 |
| 3 | 5 | d | 3.2 | lemon | 2020/1/7 |
In [21]: print(df_csv.to_latex())
\begin{tabular}{lrlrll}
\toprule
{} & col1 & col2 & col3 & col4 & col5 \\
\midrule
0 & 2 & a & 1.4 & apple & 2020/1/1 \\
1 & 3 & b & 3.4 & banana & 2020/1/2 \\
2 & 6 & c & 2.5 & orange & 2020/1/5 \\
3 & 5 & d & 3.2 & lemon & 2020/1/7 \\
\bottomrule
\end{tabular}
2.2 基本数据结构
- pandas 中具有两种基本的数据存储结构,存储一维
values
的Series
和存储二维values
的DataFrame
2.2.1 Series
Series
一般由四个部分组成,分别是序列的值data
、索引index
、存储类型dtype
、序列的名字name
- 索引也可以指定它的名字,默认为空
In [22]: s = pd.Series(data = [100, 'a', {'dic1':5}],
....: index = pd.Index(['id1', 20, 'third'], name='my_idx'),
....: dtype = 'object',
....: name = 'my_name')
In [23]: s
Out[23]:
my_idx
id1 100
20 a
third {'dic1': 5}
Name: my_name, dtype: object
- object类型
-
object
代表一种混合类型,正如上面的例子中存储了整数、字符串以及Python
的字典数据结构 -
目前
pandas
把纯字符串序列默认认为是一种object
类型的序列,但它也可以用string
类型存储 -
序列的值
data
、索引index
、存储类型dtype
、序列的名字name
、序列的长度shape
,可以通过.
的方式来获取
In [24]: s.values
Out[24]: array([100, 'a', {'dic1': 5}], dtype=object)
In [25]: s.index
Out[25]: Index(['id1', 20, 'third'], dtype='object', name='my_idx')
In [26]: s.dtype
Out[26]: dtype('O')
In [27]: s.name
Out[27]: 'my_name'
In [28]: s.shape
Out[28]: (3,)
- 取出单个索引对应的值,可以用
[index_item]
In [29]: s['third']
Out[29]: {'dic1': 5}
2.2.2 DataFrame
DataFrame
在Series
的基础上增加了列索引,一个数据框可以由二维的data
与行列索引来构造
In [30]: data = [[1, 'a', 1.2], [2, 'b', 2.2], [3, 'c', 3.2]]
In [31]: df = pd.DataFrame(data = data,
....: index = ['row_%d'%i for i in range(3)],
....: columns=['col_0', 'col_1', 'col_2'])
....:
In [32]: df
Out[32]:
col_0 col_1 col_2
row_0 1 a 1.2
row_1 2 b 2.2
row_2 3 c 3.2
- 更常见情况是采用从列索引名到数据的映射来构造数据框,同时再加上行索引
In [33]: df = pd.DataFrame(data = {'col_0': [1,2,3], 'col_1':list('abc'),
....: 'col_2': [1.2, 2.2, 3.2]},
....: index = ['row_%d'%i for i in range(3)])
....:
In [34]: df
Out[34]:
col_0 col_1 col_2
row_0 1 a 1.2
row_1 2 b 2.2
row_2 3 c 3.2
- 由于以上映射关系,在
DataFrame
中可以用[col_name]
与[col_list]
来取出相应的列与由多个列组成的表,结果分别为Series
和DataFrame
In [35]: df['col_0']
Out[35]:
row_0 1
row_1 2
row_2 3
Name: col_0, dtype: int64
In [36]: df[['col_0', 'col_1']]
Out[36]:
col_0 col_1
row_0 1 a
row_1 2 b
row_2 3 c
- 与
Series
类似,在数据框中同样可以取出相应的属性
In [37]: df.values
Out[37]:
array([[1, 'a', 1.2],
[2, 'b', 2.2],
[3, 'c', 3.2]], dtype=object)
In [38]: df.index
Out[38]: Index(['row_0', 'row_1', 'row_2'], dtype='object')
In [39]: df.columns
Out[39]: Index(['col_0', 'col_1', 'col_2'], dtype='object')
In [40]: df.dtypes # 返回的是值为相应列数据类型的Series
Out[40]:
col_0 int64
col_1 object
col_2 float64
dtype: object
In [41]: df.shape
Out[41]: (3, 3)
- 转置
DataFrame
:.T
In [42]: df.T
Out[42]:
row_0 row_1 row_2
col_0 1 2 3
col_1 a b c
col_2 1.2 2.2 3.2
2.3 常用基本函数
2.3.1 汇总函数
head, tail
函数分别表示返回表或者序列的前n
行和后n
行,其中n
默认为5:
In [46]: df.head(2)
Out[46]:
School Grade Name Gender Height Weight Transfer
0 Shanghai Jiao Tong University Freshman Gaopeng Yang Female 158.9 46.0 N
1 Peking University Freshman Changqiang You Male 166.5 70.0 N
In [47]: df.tail(3)
Out[47]:
School Grade Name Gender Height Weight Transfer
197 Shanghai Jiao Tong University Senior Chengqiang Chu Female 153.9 45.0 N
198 Shanghai Jiao Tong University Senior Chengmei Shen Male 175.3 71.0 N
199 Tsinghua University Sophomore Chunpeng Lv Male 155.7 51.0 N
info, describe
分别返回表的 信息概况 和表中 数值列对应的主要统计量
In [48]: df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 200 entries, 0 to 199
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 School 200 non-null object
1 Grade 200 non-null object
2 Name 200 non-null object
3 Gender 200 non-null object
4 Height 183 non-null float64
5 Weight 189 non-null float64
6 Transfer 188 non-null object
dtypes: float64(2), object(5)
memory usage: 11.1+ KB
In [49]: df.describe()
Out[49]:
Height Weight
count 183.000000 189.000000
mean 163.218033 55.015873
std 8.608879 12.824294
min 145.400000 34.000000
25% 157.150000 46.000000
50% 161.900000 51.000000
75% 167.500000 65.000000
max 193.900000 89.000000
info, describe
只能实现较少信息的展示,若想对一份数据集进行全面且有效的观察,特别是在列较多的情况下,推荐使用 pandas-profiling 包
2.3.2 特征统计函数
sum, mean, median, var, std, max, min
In [50]: df_demo = df[['Height', 'Weight']]
In [51]: df_demo.mean()
Out[51]:
Height 163.218033
Weight 55.015873
dtype: float64
In [52]: df_demo.max()
Out[52]:
Height 193.9
Weight 89.0
dtype: float64
quantile, count, idxmax
In [53]: df_demo.quantile(0.75) #返回分位数
Out[53]:
Height 167.5
Weight 65.0
Name: 0.75, dtype: float64
In [54]: df_demo.count() #返回非缺失值个数
Out[54]:
Height 183
Weight 189
dtype: int64
In [55]: df_demo.idxmax() #返回最大值对应的索引,idxmin是对应的函数
Out[55]:
Height 193
Weight 2
dtype: int64
- 上面所有函数由于返回的是标量,所以又称为聚合函数,有一个公共参数为
axis
- 默认为0代表逐列聚合,1表示逐行聚合
In [56]: df_demo.mean(axis=1).head() # 在这个数据集上体重和身高的均值并没有意义
Out[56]:
0 102.45
1 118.25
2 138.95
3 41.00
4 124.00
dtype: float64
2.3.3 唯一值函数
- 对序列使用
unique
,得到其唯一值组成的列表;使用nunique
得到其唯一值的个数
In [57]: df['School'].unique()
Out[57]:
array(['Shanghai Jiao Tong University', 'Peking University',
'Fudan University', 'Tsinghua University'], dtype=object)
In [58]: df['School'].nunique()
Out[58]: 4
value_counts
可以得到唯一值和其对应出现的频数
In [59]: df['School'].value_counts()
Out[59]:
Tsinghua University 69
Shanghai Jiao Tong University 57
Fudan University 40
Peking University 34
Name: School, dtype: int64
- 若想观察多个列组合的唯一值,可以使用
drop_duplicates
- 关键参数是
keep
,默认值first
表示每个组合保留第一次出现的所在行,last
表示保留最后一次出现的所在行,False
表示把所有重复组合所在的行剔除
In [60]: df_demo = df[['Gender','Transfer','Name']]
In [61]: df_demo.drop_duplicates(['Gender', 'Transfer']) #默认值为first
Out[61]:
Gender Transfer Name
0 Female N Gaopeng Yang
1 Male N Changqiang You
12 Female NaN Peng You
21 Male NaN Xiaopeng Shen
36 Male Y Xiaojuan Qin
43 Female Y Gaoli Feng
In [62]: df_demo.drop_duplicates(['Gender', 'Transfer'], keep='last')
Out[62]:
Gender Transfer Name
147 Male NaN Juan You
150 Male Y Chengpeng You
169 Female Y Chengquan Qin
194 Female NaN Yanmei Qian
197 Female N Chengqiang Chu
199 Male N Chunpeng Lv
In [63]: df_demo.drop_duplicates(['Name', 'Gender'],
....: keep=False).head() # 保留只出现过一次的性别和姓名组合
....:
Out[63]:
Gender Transfer Name
0 Female N Gaopeng Yang
1 Male N Changqiang You
2 Male N Mei Sun
4 Male N Gaojuan You
5 Female N Xiaoli Qian
In [64]: df['School'].drop_duplicates() # 在Series上也可以使用
Out[64]:
0 Shanghai Jiao Tong University
1 Peking University
3 Fudan University
5 Tsinghua University
Name: School, dtype: object
duplicated
返回是否为唯一值的布尔列表
- 和
drop_duplicates
的功能类似,但返回的不是多个列组合的唯一值 - 返回的序列,把重复元素设为
True
,否则为False
drop_duplicates
等价于把duplicated
为True
的对应行剔除
In [65]: df_demo.duplicated(['Gender', 'Transfer']).head()
Out[65]:
0 False
1 False
2 True
3 True
4 True
dtype: bool
In [66]: df['School'].duplicated().head() # 在Series上也可以使用
Out[66]:
0 False
1 False
2 True
3 False
4 True
Name: School, dtype: bool
2.3.4 替换函数
- 一般而言,替换操作是针对某一个列进行的,因此下面的例子都以
Series
举例 pandas
中的替换函数可以归纳为三类:映射替换(包含replace
方法、str.replace
方法、cat.codes
方法)、逻辑替换、数值替换
- 映射替换
- 在
replace
中,可以通过字典构造,或者传入两个列表来进行替换
In [67]: df['Gender'].replace({'Female':0, 'Male':1}).head()
Out[67]:
0 0
1 1
2 1
3 0
4 1
Name: Gender, dtype: int64
In [68]: df['Gender'].replace(['Female', 'Male'], [0, 1]).head()
Out[68]:
0 0
1 1
2 1
3 0
4 1
Name: Gender, dtype: int64
replace
特殊的方向替换method
参数为ffill
:用前面一个最近的未被替换的值进行替换method
参数为bfill
:使用后面最近的未被替换的值进行替换
In [69]: s = pd.Series(['a', 1, 'b', 2, 1, 1, 'a'])
s
Out[69]:
0 a
1 1
2 b
3 2
4 1
5 1
6 a
dtype: object
In [70]: s.replace([1, 2], method='ffill')
Out[70]:
0 a
1 a
2 b
3 b
4 b
5 b
6 a
dtype: object
In [71]: s.replace([1, 2], method='bfill')
Out[71]:
0 a
1 b
2 b
3 a
4 a
5 a
6 a
dtype: object
- 正则替换使用
str.replace
:对于replace
而言可以使用正则替换,但是当前版本对于string
类型的正则替换还存在 bug ,因此如有此需求,请选择str.replace
进行替换操作
- 逻辑替换
-
包括
where
和mask
,这两个函数是完全对称的 -
where
在传入条件为False
的对应行进行替换 -
mask
在传入条件为True
的对应行进行替换 -
当不指定替换值时,替换为缺失值
In [72]: s = pd.Series([-1, 1.2345, 100, -50])
In [73]: s.where(s<0)
Out[73]:
0 -1.0
1 NaN
2 NaN
3 -50.0
dtype: float64
In [74]: s.where(s<0, 100)
Out[74]:
0 -1.0
1 100.0
2 100.0
3 -50.0
dtype: float64
In [75]: s.mask(s<0)
Out[75]:
0 NaN
1 1.2345
2 100.0000
3 NaN
dtype: float64
In [76]: s.mask(s<0, -50)
Out[76]:
0 -50.0000
1 1.2345
2 100.0000
3 -50.0000
dtype: float64
- 传入的条件只需是与被调用的
Series
索引一致的布尔序列即可:
In [77]: s_condition= pd.Series([True,False,False,True],index=s.index)
In [78]: s.mask(s_condition, -50)
Out[78]:
0 -50.0000
1 1.2345
2 100.0000
3 -50.0000
dtype: float64
- 数值替换
- 包含
round, abs, clip
方法 round
:按照给定精度四舍五入abs
:取绝对值clip
:截断
In [79]: s = pd.Series([-1, 1.2345, 100, -50])
In [80]: s.round(2)
Out[80]:
0 -1.00
1 1.23
2 100.00
3 -50.00
dtype: float64
In [81]: s.abs()
Out[81]:
0 1.0000
1 1.2345
2 100.0000
3 50.0000
dtype: float64
In [82]: s.clip(0, 2) # 前两个数分别表示上下截断边界
Out[82]:
0 0.0000
1 1.2345
2 2.0000
3 0.0000
dtype: float64
In [83]: s.clip(0,2).replace(2,5) #将超出边界的值替换为自定义的值,但是这种方法只能把某一边的边界值换为自定义值
Out[83]:
0 0.0000
1 1.2345
2 5.0000
3 0.0000
dtype: float64
In [83]: s.mask(s>2, 5).mask(s<0, 5) #这种方法可以把超出边界的值都替换为自定义值
Out[83]:
0 5.0000
1 1.2345
2 5.0000
3 5.0000
dtype: float64
2.3.5 排序函数
- 排序共有两种方式,一是值排序(
sort_values
),二是索引排序(sort_index
)
- 值排序
- 单列排序:默认参数
ascending=True
为升序
In [83]: df_demo = df[['Grade', 'Name', 'Height', 'Weight']].set_index(['Grade','Name'])
In [84]: df_demo.sort_values('Height').head()
Out[84]:
Height Weight
Grade Name
Junior Xiaoli Chu 145.4 34.0
Senior Gaomei Lv 147.3 34.0
Sophomore Peng Han 147.8 34.0
Senior Changli Lv 148.7 41.0
Sophomore Changjuan You 150.5 40.0
In [85]: df_demo.sort_values('Height', ascending=False).head() #降序
Out[85]:
Height Weight
Grade Name
Senior Xiaoqiang Qin 193.9 79.0
Mei Sun 188.9 89.0
Gaoli Zhao 186.5 83.0
Freshman Qiang Han 185.3 87.0
Senior Qiang Zheng 183.9 87.0
- 多列排序:例如在体重相同的情况下,对身高进行排序,并且保持身高降序排列,体重升序排列
In [86]: df_demo.sort_values(['Weight','Height'],ascending=[True,False]).head()
Out[86]:
Height Weight
Grade Name
Sophomore Peng Han 147.8 34.0
Senior Gaomei Lv 147.3 34.0
Junior Xiaoli Chu 145.4 34.0
Sophomore Qiang Zhou 150.5 36.0
Freshman Yanqiang Xu 152.4 38.0
- 索引排序
-
用法和值排序完全一致
-
但是元素的值在索引中,需要指定索引层的名字或者层号,用参数
level
表示 -
需要注意的是字符串的排列顺序由字母顺序决定
In [87]: df_demo.sort_index(level=['Grade','Name'],ascending=[True,False]).head()
Out[87]:
Height Weight
Grade Name
Freshman Yanquan Wang 163.5 55.0
Yanqiang Xu 152.4 38.0
Yanqiang Feng 162.3 51.0
Yanpeng Lv NaN 65.0
Yanli Zhang 165.1 52.0
2.3.6 apply方法
apply
方法常用于DataFrame
的行迭代或者列迭代
-
axis
默认为0代表逐列聚合,1表示逐行聚合 -
apply
的参数往往是一个以序列为输入的函数 -
例如对于
.mean()
,使用apply
可以如下地写出
In [88]: df_demo = df[['Height', 'Weight']]
In [89]: def my_mean(x):
....: res = x.mean()
....: return res
In [90]: df_demo.apply(my_mean)
Out[90]:
Height 163.218033
Weight 55.015873
dtype: float64
- 利用
lambda
表达式使得书写简洁,这里的x
就指代被调用的df_demo
表中逐个输入的序列
In [91]: df_demo.apply(lambda x:x.mean())
Out[91]:
Height 163.218033
Weight 55.015873
dtype: float64
- 若指定
axis=1
,那么每次传入函数的就是行元素组成的Series
,其结果与之前的逐行均值结果一致
In [92]: df_demo.apply(lambda x:x.mean(), axis=1).head()
Out[92]:
0 102.45
1 118.25
2 138.95
3 41.00
4 124.00
dtype: float64
mad
函数返回的是一个序列中偏离该序列均值的绝对值大小的均值
-
例如序列1,3,7,10中,均值为5.25,每一个元素偏离的绝对值为4.25,2.25,1.75,4.75,这个偏离序列的均值为3.25
-
例如利用
apply
计算升高和体重的mad
指标
In [93]: df_demo.apply(lambda x:(x-x.mean()).abs().mean())
Out[93]:
Height 6.707229
Weight 10.391870
dtype: float64
- 这与使用内置的
mad
函数计算结果一致
In [94]: df_demo.mad()
Out[94]:
Height 6.707229
Weight 10.391870
dtype: float64
- 谨慎使用
apply
apply
的自由度很高,但是速度慢- 一般而言,使用
pandas
的内置函数处理和apply
来处理同一个任务,其速度会相差较多 - 只有在确实存在自定义需求的情境下才考虑使用
apply
2.4 窗口对象
pandas
中有3类窗口,分别是滑动窗口rolling
、扩张窗口expanding
以及指数加权窗口ewm
2.4.1 滑窗对象
- 使用
.rolling
得到滑窗对象,其最重要的参数为窗口大小window
In [95]: s = pd.Series([1,2,3,4,5])
In [96]: roller = s.rolling(window = 3)
In [97]: roller
Out[97]: Rolling [window=3,center=False,axis=0]
- 得到滑窗对象后,能够使用相应的聚合函数进行计算,需要注意的是窗口包含当前行所在的元素,例如在第四个位置进行均值运算时,应当计算(2+3+4)/3,而不是(1+2+3)/3
In [98]: roller.mean()
Out[98]:
0 NaN
1 NaN
2 2.0
3 3.0
4 4.0
dtype: float64
In [99]: roller.sum()
Out[99]:
0 NaN
1 NaN
2 6.0
3 9.0
4 12.0
dtype: float64
- 对于滑动相关系数或滑动协方差的计算
In [100]: s2 = pd.Series([1,2,6,16,30])
In [101]: roller.cov(s2)
Out[101]:
0 NaN
1 NaN
2 2.5
3 7.0
4 12.0
dtype: float64
In [102]: roller.corr(s2)
Out[102]:
0 NaN
1 NaN
2 0.944911
3 0.970725
4 0.995402
dtype: float64
- 支持使用
apply
传入自定义函数,其传入值是对应窗口的Series
,例如上述的均值函数可以等效表示
In [103]: roller.apply(lambda x:x.mean())
Out[103]:
0 NaN
1 NaN
2 2.0
3 3.0
4 4.0
dtype: float64
shift, diff, pct_change
是一组类滑窗函数
- 公共参数为
periods=n
,默认为1 shift
:表示取向前第n
个元素的值diff
:与向前第n
个元素做差(与Numpy
中不同,后者表示n
阶差分)pct_change
:与向前第n
个元素相比计算增长率- 这里的
n
可以为负,表示反方向的类似操作
In [104]: s = pd.Series([1,3,6,10,15])
In [105]: s.shift(2)
Out[105]:
0 NaN
1 NaN
2 1.0
3 3.0
4 6.0
dtype: float64
In [106]: s.diff(3)
Out[106]:
0 NaN
1 NaN
2 NaN
3 9.0
4 12.0
dtype: float64
In [107]: s.pct_change() #若不填充数字,默认为1
Out[107]:
0 NaN
1 2.000000
2 1.000000
3 0.666667
4 0.500000
dtype: float64
In [108]: s.shift(-1)
Out[108]:
0 3.0
1 6.0
2 10.0
3 15.0
4 NaN
dtype: float64
In [109]: s.diff(-2)
Out[109]:
0 -5.0
1 -7.0
2 -9.0
3 NaN
4 NaN
dtype: float64
- 将其视作类滑窗函数的原因是,它们的功能可以用窗口大小为
n+1
的rolling
方法等价代替
In [110]: s.rolling(3).apply(lambda x:list(x)[0]) # s.shift(2)
Out[110]:
0 NaN
1 NaN
2 1.0
3 3.0
4 6.0
dtype: float64
In [111]: s.rolling(4).apply(lambda x:list(x)[-1]-list(x)[0]) # s.diff(3)
Out[111]:
0 NaN
1 NaN
2 NaN
3 9.0
4 12.0
dtype: float64
In [112]: def my_pct(x):
.....: L = list(x)
.....: return L[-1]/L[0]-1
.....:
In [113]: s.rolling(2).apply(my_pct) # s.pct_change()
Out[113]:
0 NaN
1 2.000000
2 1.000000
3 0.666667
4 0.500000
dtype: float64
- 实现向后的滑窗操作,例如对1,2,3设定向后窗口为2的
sum
操作,结果为3,5,NaN
In [114]: s = pd.Series([1,2,3])
roller = s.rolling(window = 2)
In [115]: s = s + s.shift(-1)
Out[115]:
0 3.0
1 5.0
2 NaN
dtype: float64
2.4.2 扩张窗口
- 扩张窗口又称累计窗口,可以理解为一个动态长度的窗口
- 窗口的大小就是从序列开始处到具体操作的对应位置,其使用的聚合函数会作用于这些逐步扩张的窗口上
- 具体地说,设序列为a1, a2, a3, a4,则其每个位置对应的窗口即[a1]、[a1, a2]、[a1, a2, a3]、[a1, a2, a3, a4]
In [114]: s = pd.Series([1, 3, 6, 10])
In [115]: s.expanding().mean()
Out[115]:
0 1.000000
1 2.000000
2 3.333333
3 5.000000
dtype: float64
cummax, cumsum, cumprod
函数是典型的类扩张窗口函数
方法名 | 函数功能 |
---|---|
cumsum() | 依次给出前1、2、… 、n个数的和 |
cumprod() | 依次给出前1、2、… 、n个数的积 |
cummax() | 依次给出前1、2、… 、n个数的最大值 |
cummin() | 依次给出前1、2、… 、n个数的最小值 |
In [116]: s = pd.Series([1, 3, 6, 10])
In [117]: s.expanding().max() #cummax
Out[117]:
0 1.0
1 3.0
2 6.0
3 10.0
dtype: float64
In [118]: s.expanding().min() #cumsum
Out[118]:
0 1.0
1 1.0
2 1.0
3 1.0
dtype: float64
In [119]: s.expanding().agg(lambda x:x.prod()) #cumprod
Out[119]:
0 1.0
1 3.0
2 18.0
3 180.0
dtype: float64
注:本文整理内容来自datawhale社区(《Joyful Pandas》)和gitmodel开源课程,并少量补充查找的其他资料。