本节会记录部分处理pd.DadaFrame
、pd.Series
数据时使用到的方法
pd.DadaFrame函数
判断是否为df
if isinstance(data, pd.DataFrame):
创建DataFrame
Pandas.DataFrame(data,index,columns)
用于构建DataFrame
对象
data
可以为list
,也可以为pd.series
。需要注意的是,如果数据是单个数,需要使用中括号括起来,否则会报Index
有关错误data = {"col1":[number1],"col2":[number2]}
index
可以为别的df
的索引,也可以写一个list作为索引columns
为列表,用于标记列的名称
使用apply进行行或列遍历
Pandas.DataFrame.apply(func,axis)
用于对df进行遍历操作,类似于MATLAB
中对列进行操作实际上是对列中的每个元素进行操作
func
,我会写成lambda x: f(x)
的形式,官方中说,可以调用一个def(x)
,或者是直接使用np.sum()
之类的axis=1
就是对列中的每一个进行操作,一般就是这样
demo_df['updateTime'] = demo_df['updateTime'].apply(lambda x:x.split(' ')[0])
使用groupby进行分组操作
【S01E12】pandas之函数应用:map、apply、agg和transform - 知乎 (zhihu.com)
Pandas.DataFrame.groupby(by,axis)
用于对df进行先分组、后操作,值得注意的是,类似Matlab中,分组和操作是分开的,groupby之后只是创建了一个group对象,具体的操作还要再写
by可以是个str就是某一列的列名,或者是list,因为可以进行多级别的分组
axis就是行操作还是列操作
其他还有很参数,目前没用到,举个列子吧,说一下分组以后怎么进一步操作
demo_df.groupby(['secID','endDate','publishDate','updateTime','getDate','cat1'])['holdPct'].sum().sort_index()
输出为csv文件
Pandas.DataFrame.to_csv(filename,mode,encoding,header,index)
这个方法是把内存中的df对象保存到本地
filename
是保存文件的名称,其实也可以加上路径,就比如'\导出数据\cross\Shcategory.csv'
,但必须保证文件夹存在,否则会报错。建议在代码中加入路径不存在则使用os
创建的逻辑mode
是写入的类型,和python
写入一样的,我不太熟悉,只用到w是创建并写入,a
是追加写入encoding
是写入文件的编码格式,如果想要用Excel
打开就是gbk
,如果用编辑器查看就是utf-8
,不过pycharm
可以提醒你用gbk重新打开,不过目前来看最万能的格式是utf_8_sig
,两边打开都不会乱码header
表示是否写入表头,追加时不要表头,新写时需要写入表头index
表示是否需要写入索引,一般是不需要的,所以index=FALSE就成,仅当index含有除了序号以外的其他信息的时候,才需要写入
使用merge拼接数据
Pandas.DataFrame.merge(right,how,on,axis)
这个方法类似于Excel
中的Vlookup
了,根据关键词将两个df匹配拼接起来
right
表示需要拼接的df
,其实写成pd.merge(left_df,right_df)
亲测也可以how
表示拼接方法,可选‘left’, ‘right’, ‘outer’, ‘inner’, ‘cross’
, 默认inner
,表示仅保留两个df
共有的部分,left
表示仅保留左边left
的部分on
表示关键词列,如果左右名称不一样,可以分别使用left_on
,right_on
axis
一般就是1
了
特别的,使用merge按照Index拼接
data_df.merge(REVS5,left_index=True,right_index=True)
使用concat拼接数据
Pandas.DataFrame.concat([df1,df2],axis)
这个方法是把两个df直接拼接到一起,或许多个df也可以,没有匹配的功能,就是简单拼接
axis = {0:’index’,1:’columns’}, default 0
,意思就是说,默认为0表示根据Index进行拼接还有一些参数,排序之类的就不详细写了,注意的是两个df一定要写在中括号里面
使用replace替换数据中的元素
Pandas.Series.replace()
对Series对象中的符合规定的元素进行替换,可以用正则表达式,很不错
SecData_df['vwap'].replace(0, np.nan, inplace=True)
使用GroupBy.rank进行排序
Pandas.DataFrame.groupby().rank()
这个操作是对某列的数据进行聚类然后对其它列的属于同类数据进行数值大小排序
method
的意思是遇到相同的数值怎么算排名,如果选‘average’
,那么就会取两个rank
的平均数,导致的结果就是rank
中会出现小数,如果选‘min'
那就是都取最小的排名,如果是‘first’那就是将考前的数值设置为更小的排名ascending
标记排序顺序是从大到小还是从小到大,TRUE表示从小到大na_option
表示了对缺失值NaN怎么处理,{‘keep’,‘top’,‘bottom’}
,选为top
则是移到顶部
df.groupby(['gender'])['age'].rank()
使用roling实现滚动窗口
Pandas.DataFrame.rolling()
计算滚动窗口的均值,EMA
的主要实现方式
使用pivot数据重构
Pandas.DataFrame.pivot()
数据重构的主要实现方式,通过指定index
,columns
,values
实现对原始DataFrame
的数据重构
使用re对数据中的str数据处理
Pandas.Series.str.**
这一块就是pandas和re的结合了,但每个方法都很简单,就挨个说一下
pandas.Series.str.contains(pat)
,包含pat
返回TRUE
,pat
可以写成正则表达式,可以用|拼接多个pandas.Series.str.endswith(pat)
,以pat
结尾返回TRUE
,pat
可以写成正则表达式,但是不能拼接多个pandas.Series.str.extract(pat)
,使用pat
拆分,返回多列,然后使用apply
提取内容pandas.Series.str.len()
,返回元素长度
查询元素是否在一个list里出现
Pandas.Series.isin(values)
这个方法,总体上还是类似MatLab
,就是对一列里面的每一个元素都操作
values
为list
或者是str
如果元素在
values
这个list
中,或者就等于这个str
(不过这个有点鸡肋,干嘛不直接用==)就在对于的地方返回True
,整体上来看,也是属于筛选的某些行的操作范畴
使用drop删除指定部分
Pandas.DataFrame.drop()
这个方法就是删除指定的行了,一般第一个参数是以index
为基础的索引,实操中我一般会先做一个tag
,然后使用tag == TRUE
的index
,作为drop
的index
tag_a = self.CAdf['TradTime'].str.contains('14:5[789]:[0-9]{2}.[0-9]{3}|15:00:[0-9]{2}.[0-9]{3}')
self.SecDatadf.drop(tag_a.index[tag_a], inplace=True) # 删除提取出的数据
删除特定列
data_df.drop(columns=['aiq_date','closePrice','turnoverVol'])
序列差分
Pandas.DataFrame.diff(axis=1,periods=1)
做差分,第一个会变成NaN
- 参数
axis
表示对几列进行差分 - 参数
periods
表示差分跨度,默认为1
self.wheredf['diff'] = self.wheredf[['Vgroup']].diff()
使用iterrows生成迭代器
for index, row in data.iterrows():
# 针对每行数据计算变动
row_dict = {}
row_dict['index'] = index
row_dict['updateTime'] = row['updateTime']
if index > 0:
for col in cols:
if data.iloc[index - 1][col] == np.NaN or data.iloc[index][col] == np.NaN:
row_dict[col + '_rate'] = np.NaN
d1 = float(data.iloc[index - 1][col])
d2 = float(data.iloc[index][col])
rate = (d2 - d1) / d1
row_dict[col + '_rate'] = rate
rate_df = rate_df.append(row_dict, ignore_index=True)
return rate_df
使用GroupBy生产遍历序列
for author_group, group_df in self.mergedata.groupby(['author', 'secCode']):
# 按照每年分组查询
for year, year_df in group_df.groupby('foreYear'):
year_df = year_df.sort_values(by='writeDate') # 对研报预测时间进行排序
year_df[field + '_forecast_change'] = year_df.groupby('author')[field].apply(lambda x: (x - x.shift(1)) / x.shift(1)) # 根据要求公式得到想预测字段的变动并储存
year_df = year_df[['author', 'secName', 'foreYear', field + '_forecast_change', 'writeDate', 'publishDate']]
self.result = pd.concat([self.result, year_df])
DataFrame切片
loc
loc对应的是index,loc中可以直接写对Series对象的逻辑判断
subset.loc[subset['upLimitDay'] == 0]
iloc
iloc与loc的区别是,loc以index为基准,iloc则是忽略index直接以行数取出。
当然,iloc也可以取多行,例如:
df2 = self.wheredf.iloc[where:, :]
直接切
使用尾追一个列表,表示取多少到多少位
target_position[0:10]
切出一个元素
想要提取一个元素(数值或str),目前的方法就是先取为list再取其第一个元素
price = list(temp_df[name])[0]
这两种方法也可以
self.SecID = self.SecDatadf['SecurityID'][0]
self.wheredf.loc[indexi]['Vgroup']
pandas分箱
主要步骤是设置箱子bins,注意bins的每个相邻元素之间组成的区间为箱子区间,所以bins元素个数要比箱子个数多一个;然后就是使用Pd.cut进行分箱,几个参数labels为各个箱子的标签,retbins:获取边界值列表,include_lowest字面意思,righ:包含右边界与否
bins = [i * self.targenum for i in range(0, self.cellNum + 1)] # 设置箱子
pd.cut(np.cumsum(self.SecDatadf.TradVolume), bins, labels=range(1, self.cellNum + 1),retbins=False,include_lowest=True, right=True)