本次分享一些关于Python使用的心得体会。主要是数据分析方面。
一、为什么用Python
在经验研究的心得分享(202211)一文中,举例所用的软件是STATA。这次聊Python。二者不同难以尽说,兹举二三:
关于编程的现成性和灵活性方面。Python和STATA都有丰富的软件包,即现成的函数,容易查到,这是两者的共性。但Python的语言相较STATA更为基础,一方面自己编、自己学确实要花费不少功夫,另一方面,这也意味着更大的灵活性,如,自己编函数比较方便。编函数的目的就是对一些需重复使用的语句段落不用每次都写,可以调用自己编的函数,调整输入的变量就可以了,节约空间(看着不乱)、节约力气。
STATA在一些重要函数和常见分析方法方面,资源比Python更丰富一些,拿来就能用,这是STATA的优势。但总归在编写和调用自己的函数方面不如Python方便(个人感觉)。因此两者各有优势,不妨互补。
关于数据处理的速度方面。Python在处理大规模数据时速度快。比如超过4G的日度或月度股价数据、季度或年度公司财务数据,能够在import pandas as pd后,通过pd.read_csv()函数较为快速地导入。
关于画图方面。Python有许多软件包,比较常用的是matplotlib。它提供了与MATLAB中的画图函数类似的函数。能够画出好看的图像,且自己编程调整坐标轴、背景、颜色等属性也比较灵活。还有,速度快,在画地图方面,比MATLAB快很多,当然也需要前期设定好输入的格式(这一步自感很不容易)。
二、数据处理方面的注意事项
数据处理常用的软件包为pandas,要提前安装好。以PyCharm这个环境为例(可在它的公司网页上下载,社区版的是免费的),页面底端有“Python Packages”窗口,点击,输入软件包名称进行搜索,之后点击“Add Package”即可(自感这一安装方式比通过终端的安装方式更直观)。安装好后,在程序的开头输入:import pandas as pd。
关于数据导入。在导入数据时,如果发现数据不大而速度却很慢,不要被动等待,可以考虑换其他方法。比如,在导入xlsx格式的文件时,会用到pd.read_excel()函数,但是这个函数一般会要求安装openpyxl软件包,即使安装了之后,速度还是慢。这时候可以考虑用pd.read_csv()函数,可以把原来的xlsx另存为csv格式(如果不是太大,还能够打开的话)。
关于使用循环。简单说:慎用循环,但也不要不用循环。Python处理的数据量一般较大,比如一个面板数据,有500个月,80000(八万)个公司。如果对个体一一用循环,会比较费时,对时间则不然。下面用两个练习说明。
练习1:对每一个个体的某个变量,计算它一段时间区间内的累加。
这时如果对80000个个体(COMPANYID)去使用for循环,会很花时间。这时候可以用groupby函数,下面以为每个公司生成它存续期间的月度回报率动量为例:
T['RET_L1'] = np.log(1+0.01*T.groupby('COMPANYID')['RET'].shift(1))
T['MOM_temp1'] = T.groupby('COMPANYID')['RET_L1'].transform(lambda s: s.rolling(11, min_periods=9).sum())
T['MOM_temp2'] = np.exp(T['MOM_temp1'])
T['MOM'] = 100*(T['MOM_temp2']-1)
其中第2行就使用了groupby函数,然后在每一个group(即一个公司的RET_L1变量的时间序列数据)里,计算每个月的某个需要生成的变量(用到了pandas的滚动窗口连加,没有连乘,故有上下几行的处理;np是NumPy函数,开头要写好import numpy as np)。
练习2:对每个月的动量变量进行缩尾处理。
在这个练习中,循环的个体就不是公司,而是时间(DATE),它的数量不多。因此循环不费时,而且能看到循环的过程,心里比较踏实:
winsorized_values = []
for name, group in T.groupby(T['DATE']):
print(name)
winsorized_values.append(list(winsorize(group['MOM'].values, limits=[0.005, 0.005])))
T.loc[:, 'MOM'+'W'] = [item for sublist in winsorized_values for item in sublist]
关于编写函数。如开头所说,Python能够较为方便地编写函数。一个心得体会是:可以编函数,但不必事事都如此。在一些重复性较强的任务中,可以自己编函数,比如对很多变量样本进行描述性统计:
def myfunc(T, x):
mean_x = T.groupby('groupingvariable')[x].mean().mean().round(2)
std_x = T.groupby('groupingvariable')[x].std().mean().round(2)
result = [mean_x, std_x]
return result
但是如果在目前的能力范围内,不会编太复杂的函数,或担心使用函数后思路会乱,可以不编函数,按部就班地一句一编、一句一执行。
关于程序包兼容性。兼容性出问题导致无法使用程序包时,不必急于去找补丁,因为有时找来了也未必能用,以后每个程序都带着补丁看着也乱。可以尝试用最新版,即在“Python Packages”窗口下载安装最新版。如果项目间隔时间较长,许多操作印象已经模糊,打开时又发现一些程序包运行不了,可以考虑重新建一个文件夹,在这个文件夹里新建一个项目(project)。然后重新配置程序包。