Python处理二维的dataframe数据主要依靠pandas包。这一点与R语言不同,R中处理dataframe的包是多面开花。不过现在这些处理函数慢慢有语法大一统的趋势,如tidyverse生态链。
在处理数据常常会遇到长宽数据互转,如从Wind数据库导出的公司财务数据。在Stata和R中已经有比较便捷的处理方法。
下面列示一下pandas包的处理方法。
首先,生成一份模拟数据。
import pandas as pd
import numpy as np
df=pd.DataFrame(np.random.rand(3,6),columns=['x', 'lev2015','roa2015', 'roa2016', 'lev2016','lev2017'])
df['stkcd']=['a1','a2','a3']
df
Out[1]:
x lev2015 roa2015 roa2016 lev2016 lev2017 stkcd
0 0.434583 0.352021 0.155295 0.307686 0.226555 0.718034 a1
1 0.440119 0.051882 0.667143 0.995478 0.114729 0.996174 a2
2 0.292902 0.516601 0.157647 0.066176 0.506407 0.968796 a3
然后开始从长转为宽。
df=df.melt(id_vars=['stkcd','x'],value_vars=['lev2015','roa2015', 'roa2016', 'lev2016','lev2017'],var_name='name',value_name='score')
df
Out[2]:
stkcd x name score
0 a1 0.434583 lev2015 0.352021
1 a2 0.440119 lev2015 0.051882
2 a3 0.292902 lev2015 0.516601
3 a1 0.434583 roa2015 0.155295
4 a2 0.440119 roa2015 0.667143
5 a3 0.292902 roa2015 0.157647
6 a1 0.434583 roa2016 0.307686
7 a2 0.440119 roa2016 0.995478
8 a3 0.292902 roa2016 0.066176
9 a1 0.434583 lev2016 0.226555
10 a2 0.440119 lev2016 0.114729
11 a3 0.292902 lev2016 0.506407
12 a1 0.434583 lev2017 0.718034
13 a2 0.440119 lev2017 0.996174
14 a3 0.292902 lev2017 0.968796
但是仔细一看,还需要再转一次。把name分割为两个变量。
df['year']=df['name'].str.slice(3,7)
df['name']=df['name'].str.slice(0,3)
df
Out[3]:
stkcd x name score year
0 a1 0.434583 lev 0.352021 2015
1 a2 0.440119 lev 0.051882 2015
2 a3 0.292902 lev 0.516601 2015
3 a1 0.434583 roa 0.155295 2015
4 a2 0.440119 roa 0.667143 2015
5 a3 0.292902 roa 0.157647 2015
6 a1 0.434583 roa 0.307686 2016
7 a2 0.440119 roa 0.995478 2016
8 a3 0.292902 roa 0.066176 2016
9 a1 0.434583 lev 0.226555 2016
10 a2 0.440119 lev 0.114729 2016
11 a3 0.292902 lev 0.506407 2016
12 a1 0.434583 lev 0.718034 2017
13 a2 0.440119 lev 0.996174 2017
14 a3 0.292902 lev 0.968796 2017
此时把name转回去即可(从变量的转成列变量的名)。这个就是我们想要的数据,不信你可以用df.to_csv('wide_long.csv')导出数据试试看。具体如下。
df=df.pivot_table(index=['stkcd','x','year'], columns='name', values='score')
df
Out[4]:
name lev roa
stkcd x year
a1 0.434583 2015 0.352021 0.155295
2016 0.226555 0.307686
2017 0.718034 NaN
a2 0.440119 2015 0.051882 0.667143
2016 0.114729 0.995478
2017 0.996174 NaN
a3 0.292902 2015 0.516601 0.157647
2016 0.506407 0.066176
2017 0.968796 NaN
不过呢,这个数据太难看了。进一步处理如下。
df=df.reset_index()
df
Out[5]:
name stkcd x year lev roa
0 a1 0.434583 2015 0.352021 0.155295
1 a1 0.434583 2016 0.226555 0.307686
2 a1 0.434583 2017 0.718034 NaN
3 a2 0.440119 2015 0.051882 0.667143
4 a2 0.440119 2016 0.114729 0.995478
5 a2 0.440119 2017 0.996174 NaN
6 a3 0.292902 2015 0.516601 0.157647
7 a3 0.292902 2016 0.506407 0.066176
8 a3 0.292902 2017 0.968796 NaN
最后附图(点击可以放大)。一般的长宽型都可以按照这个思路操作,只是会根据语言工具的差异略有调整。操作过程与版本信息示意图
问:为什么模拟那么丑的df?
答:有时候现实的df就很丑。
问:为什么这么写?麻烦,长。
答:通用,不惧df的美丑。
问:有更好的操作么?
答:靠你自动手?