dan匿名函数与map方法:
f=lambda x:2x
y=lambda a,b:a+b
[(lambda x:2*x)(i) for i in range(5)]
而map返回的时一个map对象,需要通过list转为列表
print(list(map(lambda x:2*x,range(5))))
也可以对多个输入值的函数映射
print(list(map(lambda x,y:str(x)+'_'+y,range(5),list('abcde'))))
#['0_a', '1_b', '2_c', '3_d', '4_e']
zip对象与enumerate方法:
zip函数能够把多个可迭代对象打包成一个元祖构成的可迭代对象,它返回了一个ziop对象
通过tuple,list可以得到相应的打包结果:
L1,L2,L3=list('abc'),list('def'),list('hij')
print(list(zip(L1,L2,L3)))
#[('a', 'd', 'h'), ('b', 'e', 'i'), ('c', 'f', 'j')]
print(tuple(zip(L1,L2,L3)))
#(('a', 'd', 'h'), ('b', 'e', 'i'), ('c', 'f', 'j'))
for i,j,k in zip(L1,L2,L3):
print(i,j,k)
#a d h
#b e i
#c f j
enumerate是一种特殊的打包,可以再迭代内容的时候绑定迭代元素的遍历号
for index, value in enumerate(L):
print(index, value)
#0 a
#1 b
#2 c
for j,k in enumerate(zip(L1,L2)):
print(j,k)
#0 ('a', 'd')
#1 ('b', 'e')
#2 ('c', 'f')
用zip实现上述功能
for j,k in zip(range(len(L1)),L1):
print(j,k)
#0 a
#1 b
#2 c
但是enumerate可以实现对zip压缩的组合进行遍历,但是zip只能实现上述简单的
也可以利用字典和zip对两个列表建立映射
print(dict(zip(L1,L2)))
#{'a': 'd', 'b': 'e', 'c': 'f'}
利用zip和*可以进行解压
print(list(zip(L1,L2,L3)))
print(list(zip(*(zip(L1,L2,L3)))))
#[('a', 'd', 'h'), ('b', 'e', 'i'), ('c', 'f', 'j')]
#[('a', 'b', 'c'), ('d', 'e', 'f'), ('h', 'i', 'j')]
利用np.ix_在对应的维度上进行索引:
a=np.arange(9).reshape(3,3)
print(a)
print(a[np.ix_([0,1],[1,2])]) #输出索引0到1行中的列索引为1和2的值
#[[0 1 2]
#[3 4 5]
#[6 7 8]]
#[[1 2]
# [4 5]]
也可以用布尔值来进行输出
print(a[np.ix_([True,False,True],[True,False,True])])
#输出行索引中为True的行中列索引为True的值
#[[0 2]
# [6 8]]
where函数:一种条件函数,可以指定满足条件与不满足条件位置的对应填充值
a=np.arange(9).reshape(-1,9)
print(a)#[[0 1 2 3 4 5 6 7 8]]
print(np.where(a>4,a,7)) #[[7 7 7 7 7 5 6 7 8]]
print(a)#[[0 1 2 3 4 5 6 7 8]]
从结果中可以看出,该操作并不会改变原始数据
any
指当序列至少 存在一个 True
或非零元素时返回True
,否则返回False
all
指当序列元素 全为 True
或非零元素时返回True
,否则返回False
a = np.array([0,1])
a.any()#True
a.all()#False
cumprod
, cumsum
, diff
cumprod
, cumsum
分别表示累乘和累加函数,返回同长度的数组,diff
表示和前一个元素做差,由于第一个元素为缺失值,因此在默认参数情况下,返回长度是原数组减1
a=np.linspace(0,20,5)
print(a) #[ 0. 5. 10. 15. 20.]
print(a.cumprod())#[0. 0. 0. 0. 0.]
print(a.cumsum())#[ 0. 5. 15. 30. 50.]
print(np.diff(a))#[5. 5. 5. 5.]
文件读取:
读取csv文件是可以用如下代码读取,但是如果csv文件时xls等文件直接改后缀生成
则可能报错:”pandas.errors.ParserError: Error tokenizing data. C error:.......“
在读取内容包含中文字符的文件时可以加入参数encoding='gbk',如果还不行,可以添加
error_bad_lines=False将错误行跳过不解析
还可以用pip install chardet安装包chardet用如下代码返回文件编码格式
# 获取文件编码类型
def get_encoding(file):
# 二进制方式读取,获取字节数据,检测类型
with open(file, 'rb') as f:
return chardet.detect(f.read())['encoding']
cs=pd.read_csv('hh.csv')
print(cs)#显示的时候可以将文件头也显示出来
当上述办法还不行时就用error_bad_lines=False跳过错误行不解析
cs=pd.read_table('新建文本文档.txt',encoding='gbk',error_bad_lines=False)
读取txt文件:
tx=pd.read_table('hh.txt')
print(tx)
读取excel文件:
ex=pd.read_excel('hh.xlsx')
print(ex)
xlrd更新到了2.0.1版本,只支持.xls文件。所以pandas.read_excel(‘xxx.xlsx’)会报错
可以通过
pip uninstall xlrd
pip install xlrd==1.2.0安装老版本的xlrd
也可以用openpyxl代替xlrd打开.xlsx文件:
df=pandas.read_excel(‘data.xlsx’,engine=‘openpyxl’)
上述的函数都可以加入公共参数header=None,表示第一列不作为列名。
ex=pd.read_excel('hh.xlsx',header=None)
print(ex)
也可利用参数index_col来指定哪一列作为索引
ex=pd.read_excel('hh.xlsx',index_col=[0,1])
#以文件中第一列和第二列作为所以
usecols表示读取列的集合
pd.read_excel('hh.xlsx',usecols=[0,1])
#读取文件中的第一列和第二列
nrows表示读取的行数,
pd.read_excel('hh.xlsx',nrows=3)
#读取文件中的前面三行
在在读取txt
文件时,经常遇到分隔符非空格的情况,read_table
有一个分割参数sep
,它使得用户可以自定义分割符号,进行txt
数据的读取。例如,下面的读取的表以||||
为分割:
pd.read_table('hh.txt',sep='\|\|\|\|',engine='python')
#在使用read_table的时候需要注意,参数sep中使用的是正则表达式,
#因此需要对|进行转义变成\|,否则无法读取到正确的结果。
数据写入:
cs.to_csv('cs.csv',index=False)
cs.to_excel('cs.xlsx',index=False)
pandas
中没有定义to_table
函数,但是to_csv
可以保存为txt
文件,并且允许自定义分隔符,常用制表符\t
分割:
cs.to_csv('../data/my_txt_saved.txt', sep='\t', index=False)
如果想要把表格快速转换为markdown
和latex
语言,可以使用to_markdown
和to_latex
函数,此处需要安装tabulate
包。
print(df_csv.to_markdown())
print(df_csv.to_latex())
基本数据结构:
pandas
中具有两种基本的数据存储结构,存储一维values
的Series
和存储二维values
的DataFrame
,在这两种结构上定义了很多的属性和方法
Series
一般由四个部分组成,分别是序列的值data
、索引index
、存储类型dtype
、
序列的名字name
。其中,索引也可以指定它的名字,默认为空。
s=pd.Series(data=[100,'1',{'dic':5}]
,index=pd.Index(['id1',20,'third'],name='my_idx')
,dtype='object',name='my_name'
)
print(s) #输出s的内容
print('----')
print(s[20])#输出索引为20的值
print(s.index)#输出s的索引
print(s.name)#输出s的name
print(s.values)#输出s的值
print(s.dtype)#输出s的类型
print(s.shape)#输出s的长度
#my_idx
#id1 100
#20 1
#third {'dic': 5}
#Name: my_name, dtype: object
#----
#1
#Index(['id1', 20, 'third'], dtype='object', name='my_idx')
#my_name
#[100 '1' {'dic': 5}]
#object
#(3,)
DataFrame:
在Series的基础上增加了列索引,一个数据框可以由二维的data与行列索引来构造:
da=[[1,'q',3,9.9],[2,'b',2.2],[3,'c']]
df=pd.DataFrame(data=da,index=['row_%d'%i for i in range(3)],
columns=['c0','c1','c2','c3'])
print(df)
# c0 c1 c2 c3
#row_0 1 q 3.0 9.9
#row_1 2 b 2.2 NaN
#row_2 3 c NaN NaN
#da的第一个元素中里面由四列,所以最终colums设置为4个,第二个人和第三个元素
#没有4列,所以没有的位置就设置为NaN
print('下面为属性')
print(df.values)
print(df.shape)
print(df.index)
print(df.columns)
print(df.dtypes)
#[[1 'q' 3.0 9.9]
# [2 'b' 2.2 nan]
# [3 'c' nan nan]]
#(3, 4)
#Index(['row_0', 'row_1', 'row_2'], dtype='object')
#Index(['c0', 'c1', 'c2', 'c3'], dtype='object')
#c0 int64
#c1 object
#c2 float64
#c3 float64
#dtype: object
但是更多的时候回采用从索引名到数据映射来构造数据框,同时再加上行索引:
da1=pd.DataFrame(data={'c1':[1,2,3],
'c2':[11,22,33],
'c3':[111,222,000],
'c4':[444, 2222,88]},
index=['row_%d'%i for i in range(3)])
print(da1)
# c1 c2 c3 c4
#row_0 1 11 111 444
#row_1 2 22 222 2222
#row_2 3 33 0 88
#此种方法与前面一种相比,此方法在初始化元素时
#每一行一列的元素都不能少,否则报错
#而上述少了的部分可以自动填补为NaN
print('下面为属性')
print(da1.values)
print(da1.index)
print(da1.shape)
print(da1.columns)
print(da1.dtypes)
print(da1.T)#转置输出
下面为属性
#[[ 1 11 111 444]
# [ 2 22 222 2222]
# [ 3 33 0 88]]
#Index(['row_0', 'row_1', 'row_2'], dtype='object')
#(3, 4)
#Index(['c1', 'c2', 'c3', 'c4'], dtype='object')
#c1 int64
#c2 int64
#c3 int64
#c4 int64
#dtype: object
# row_0 row_1 row_2
#c1 1 2 3
#c2 11 22 33
#c3 111 222 0
#c4 444 2222 88
汇总函数:head和tail函数分别表示返回表或者序列的前n行和后n行,其中n默认为5
print(df.head(3))
print(df.tail(3))
info,describe分别返回表的信息概况和表中数值列对应的主要统计量:
print(df.info())
#<class 'pandas.core.frame.DataFrame'>
#RangeIndex: 200 entries, 0 to 199
#Data columns (total 10 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
# 7 Test_Number 200 non-null int64
# 8 Test_Date 200 non-null object
# 9 Time_Record 200 non-null object
#dtypes: float64(2), int64(1), object(7)
#memory usage: 15.8+ KB
print(df.describe())
# Height Weight Test_Number
#count 183.000000 189.000000 200.000000
#mean 163.218033 55.015873 1.645000
#std 8.608879 12.824294 0.722207
#min 145.400000 34.000000 1.000000
#25% 157.150000 46.000000 1.000000
#50% 161.900000 51.000000 1.500000
#75% 167.500000 65.000000 2.000000
#max 193.900000 89.000000 3.000000
特征统计函数:
quantile,count,idmax,分别返回的是分位数、非缺失值个数、最大值对应的索引
print(df.quantile(0.75))#返回3/4分位数
print(df.count())#非缺失值个数
print(df.idxmax())#最大值对应的索引
print(df.idxmin())#最小值对应的索引
上面这些所有的函数,由于操作后返回的是标量,所以又称为聚合函数,它们有一个公共参数axis
,默认为0代表逐列聚合,如果设置为1则表示逐行聚合:
print(df.mean(axis=1).head()) #按行集合,并显示前5个结果
#0 102.45
#1 118.25
#2 138.95
#3 41.00
#4 124.00
#dtype: float64
唯一值函数:对序列使用unique
和nunique
可以分别得到其唯一值组成的列表和唯一值的个数:
print(df['school'].unique())#输出school索引下的不重复的唯一值
#array(['Shanghai Jiao Tong University', 'Peking University',
'Fudan University', 'Tsinghua University'], dtype=object)
print(df['school'].nunique())#school索引下的不重复的唯一值的数量
#4
value_counts可以得到唯一值和其出现的频数:
print(df['school'].value_counts())
#Tsinghua University 69
#Shanghai Jiao Tong University 57
#Fudan University 40
#Peking University 34
#Name: School, dtype: int64
如果想要观察多个列组合的唯一值,可以使用drop_duplicates
。其中的关键参数是keep
,默认值first
表示每个组合保留第一次出现的所在行,last
表示保留最后一次出现的所在行,False
表示把所有重复组合所在的行剔除。
df_demo = df[['Gender','Transfer','Name']]
print(df_demo)#该操作将表中['Gender','Transfer','Name']的数据都输出
# Gender Transfer Name
#0 Female N Gaopeng Yang
#1 Male N Changqiang You
#2 Male N Mei Sun
#3 Female N Xiaojuan Sun
#4 Male N Gaojuan You
#... ... ... ...
#195 Female N Xiaojuan Sun
#196 Female N Li Zhao
#197 Female N Chengqiang Chu
#198 Male N Chengmei Shen
#199 Male N Chunpeng Lv
print(df_demo.drop_duplicates(['Gender', 'Transfer']))
# 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
#上述的输出是输出'Gender'和'Transfer'两个列组成的唯一组合(即使用两个的不同组合来作为索引)
print(df_demo.drop_duplicates(['Gender', 'Transfer'], keep='last'))
# 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
print(df_demo.drop_duplicates(['Name', 'Gender'], keep=False).head())
# 保留只出现过一次的性别和姓名组合
#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
print(df_demo.drop_duplicates(['Name', 'Gender']).head())
#Gender Transfer Name
#0 Female N Gaopeng Yang
#1 Male N Changqiang You
#2 Male N Mei Sun
#3 Female N Xiaojuan Sun
#4 Male N Gaojuan You
#与上述有keep=False的结果不一样的原因是因为
#Gender Name
#Female Xiaojuan Sun
这个组合在表的后续还出现过,所以在有keep=False的中该组合就被删除了
drop_duplicates也可以在Series上使用,即上面的索引不一定要是两个列索引的组合,一个列索引也可以例如:df['school'].drop_duplicates()
此外,duplicated
和drop_duplicates
的功能类似,但前者返回了是否为唯一值的布尔列表,其keep
参数与后者一致。其返回的序列,把重复元素设为True
,否则为False
。 drop_duplicates
等价于把duplicated
为True
的对应行剔除。
print(df_demo.duplicated(['Gender', 'Transfer']).head())
#0 False
#1 False
#2 True
#3 True
#4 True
#dtype: bool
#上述结果False表示没有重复的,True表示有重复的
print(df['School'].duplicated().head()) # 在Series上也可以使用
#0 False
#1 False
#2 True
#3 False
#4 True
#Name: School, dtype: bool
替换函数:
一般而言,替换操作是针对某一个列进行的,因此下面的例子都以Series
举例。pandas
中的替换函数可以归纳为三类:映射替换、逻辑替换、数值替换。其中映射替换包含replace
方法
在`replace`中,可以通过字典构造,或者传入两个列表来进行替换:
print(df['Gender'].replace({'Female':0,'Male':1}).head())#两字典形式
#0 0
#1 1
#2 1
#3 0
#4 1
#Name: Gender, dtype: int64
print(df['Gender'].replace(['Female', 'Male'], [0, 1]).head())#列表形式
另外,replace
还有一种特殊的方向替换,指定method
参数为ffill
则为用前面一个最近的未被替换的值进行替换,bfill
则使用后面最近的未被替换的值进行替换。
s=pd.Series(['a',1,'b',2,1,1,'a'])
print(s.replace([1,2],method='ffill'))
#0 a #不被替换,原样输出
#1 a #s中其前面最近的一个没被替换的是a,固被替换成a
#2 b #不被替换,原样输出
#3 b #s中其前面最近的一个没被替换的是b,固被替换成b,后面输出同原因
#4 b
#5 b
#6 a
dtype: object
print(s.replace([1, 2], method='bfill'))
#0 a #不被替换,原样输出
#1 b #s中其后面最近的一个没被替换的是b,固被替换成b
#2 b #原样输出
#3 a #s中其后面最近的一个没被替换的是a,固被替换成a,后面的同原因
#4 a
#5 a
#6 a
#dtype: object
逻辑替换包括了where
和mask
,这两个函数是完全对称的:where
函数在传入条件为False
的对应行进行替换,而mask
在传入条件为True
的对应行进行替换,当不指定替换值时,替换为缺失值。
s = pd.Series([-1, 1.2345, 100, -50])
print(s.where(s<0))
#0 -1.0
#1 NaN
#2 NaN
#3 -50.0
#dtype: float64
print(s.where(s<0,100))
#0 -1.0
#1 100.0
#2 100.0
#3 -50.0
#dtype: float64
print(mask(s<0))
#0 NaN
#1 1.2345
#2 100.0000
#3 NaN
#dtype: float64
print(mask(s<0,-50))
#0 -50.0000
#1 1.2345
#2 100.0000
#3 -50.0000
#dtype: float64
需要注意的是,传入的条件只需是与被调用的Series
索引一致的布尔序列即可:
s_condition= pd.Series([True,False,False,True],index=s.index)
print(s.mask(s_condition, -50))
#0 -50.0000
#1 1.2345
#2 100.0000
#3 -50.0000
#dtype: float64
print(s.where(s_condition, -50))
#0 -1.0
#1 -50.0
#2 -50.0
#3 -50.0
#dtype: float64
clip:表示截断
s = pd.Series([-1, 1.2345, 100, -50])
print(s.clip(0,2)) #小于0的取0,大于2的取1
#0 0.0000
#1 1.2345
#2 2.0000
#3 0.0000
#dtype: float64
排序函数:排序共有两种方式,其一为值排序,其二为索引排序,对应的函数是sort_values
和sort_index
。
set_index可以设置列作为索引
df_demo = df[['Grade', 'Name', 'Height', 'Weight']].set_index(['Grade','Name'])
#将"Grade"和”Name“设置为索引列
print(df_demo.head(3))
# Height Weight
#Grade Name
#Freshman Gaopeng Yang 158.9 46.0
# Changqiang You 166.5 70.0
#Senior Mei Sun 188.9 89.0
#对身高进行排序,默认参数ascending=True为升序:
print(df_demo.sort_values('Height').head())
# 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
#在排序中,经常遇到多列排序的问题,比如在体重相同的情况下,对身高进行排序
#并且保持身高降序排列,体重升序排列:
print(df_demo.sort_values(['Weight','Height'],ascending=[True,False]).head())
# 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
表示。另外,需要注意的是字符串的排列顺序由字母顺序决定
print(df_demo.sort_index(level=['Grade','Name'],ascending=[True,False]).head())
# 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
apply方法:
apply
方法常用于DataFrame
的行迭代或者列迭代,它的axis
含义与统计聚合函数一致,apply
的参数往往是一个以序列为输入的函数。例如对于.mean()
,使用apply
可以如下地写出:
df_demo = df[['Height', 'Weight']]
def my_mean(x):
res = x.mean()
return res
print(df_demo.apply(my_mean))
#Height 163.218033
#Weight 55.015873
#dtype: float64
#也可以用下列简略表达
print(df_demo.apply(lambda x:x.mean()))
#若指定axis=1,那么每次传入函数的就是行元素组成的Series,其结果与之前的逐行均值结果一致。
print(df_demo.apply(lambda x:x.mean(), axis=1).head())
#Grade Name
#Freshman Gaopeng Yang 102.45
# Changqiang You 118.25
#Senior Mei Sun 138.95
#Sophomore Xiaojuan Sun 41.00
Gaojuan You 124.00
#dtype: float64
mad
函数返回的是一个序列中偏离该序列均值的绝对值大小的均值,例如序列1,3,7,10中,均值为5.25,每一个元素偏离的绝对值为4.25,2.25,1.75,4.75,这个偏离序列的均值为3.25。现在利用apply
计算升高和体重的mad
指标:
print(df_demo.apply(lambda x:(x-x.mean()).abs().mean()))
#Height 6.707229
#Weight 10.391870
#dtype: float64
print(df_demo.mad())
#Height 6.707229
#Weight 10.391870
#dtype: float64
pandas
中有3类窗口,分别是滑动窗口rolling
、扩张窗口expanding
以及指数加权窗口ewm
滑动窗口:要使用滑窗函数,就必须先要对一个序列使用.rolling
得到滑窗对象,其最重要的参数为窗口大小window
s = pd.Series([1,2,3,4,5])
roller = s.rolling(window = 3)
print(roller)
#Rolling [window=3,center=False,axis=0]
#在notebook中可以用list(s.rolling(3)对rolling输出
#但是pycharm会报错
#下面是notebook中的输出结果
#[0 1
# dtype: int64, 0 1
# 1 3
# dtype: int64, 0 1
# 1 3
# 2 6
# dtype: int64, 1 3
# 2 6
# 3 10
# dtype: int64, 2 6
# 3 10
# 4 15
# dtype: int64]
在得到了滑窗对象后,能够使用相应的聚合函数进行计算,需要注意的是窗口包含当前行所在的元素,例如在第四个位置进行均值运算时,应当计算(2+3+4)/3,而不是(1+2+3)/3:
print(roller.mean())
#0 NaN #(1+Nan+Nan)/3
#1 NaN #(2+Nan+Nan)/3
#2 2.0 #(1+2+3)/3
#3 3.0 #(2+3+4)/3
#4 4.0 #(3+4+5)/3
#dtype: float64
shift, diff, pct_change
是一组类滑窗函数,它们的公共参数为periods=n
,默认为1,分别表示取向前第n
个元素的值、与向前第n
个元素做差(与Numpy
中不同,后者表示n
阶差分)、与向前第n
个元素相比计算增长率。这里的n
可以为负,表示反方向的类似操作。
s = pd.Series([1,3,6,10,15])
print(s.shift(2))
#0 NaN
#1 NaN
#2 1.0
#3 3.0
#4 6.0 #去到s中索引为n的为止
#dtype: float64
print(s.diff(3))
#0 NaN
#1 NaN
#2 NaN
#3 9.0 #10-1
#4 12.0 #15-3
#dtype: float64
print(s.pct_change())
#0 NaN
#1 2.000000 #(3-1)/1
#2 1.000000 #(6-3)/3
#3 0.666667 #(10-6)/6
#4 0.500000
#dtype: float64
将其视作类滑窗函数的原因是,它们的功能可以用窗口大小为n+1
的rolling
方法等价代替:
s = pd.Series([1,3,6,10,15])
print(s.rolling(3).apply(lambda x:list(x)[-1]) #对当前rolling最后一个值进行操作
0 NaN #此时rolling(3)为[0 1
dtype: int64]
1 NaN #此时rolling(3)为[0 1
1 3
dtype: int64]
2 6.0 #此时rolling(3)为[0 1
1 3
2 6
dtype: int64]
3 10.0
4 15.0
dtype: float64
s.rolling(4).apply(lambda x:list(x)[-1]-list(x)[0]) # s.diff(3)
#0 NaN
#1 NaN
#2 NaN
#3 9.0
#4 12.0
#dtype: float64
def my_pct(x):
L = list(x)
return L[-1]/L[0]-1
s.rolling(2).apply(my_pct) # s.pct_change()
#0 NaN
#1 2.000000
#2 1.000000
#3 0.666667
#4 0.500000
#dtype: float64
扩张窗口
扩张窗口又称累计窗口,可以理解为一个动态长度的窗口,其窗口的大小就是从序列开始处到具体操作的对应位置,其使用的聚合函数会作用于这些逐步扩张的窗口上。具体地说,设序列为a1, a2, a3, a4,则其每个位置对应的窗口即[a1]、[a1, a2]、[a1, a2, a3]、[a1, a2, a3, a4]。
s = pd.Series([1, 3, 6, 10])
s.expanding().mean()
#0 1.000000
#1 2.000000
#2 3.333333
#3 5.000000
#dtype: float64