熊猫中从长到大的数据转换

时间:2016-05-24 15:46:52

标签: python pandas

我有以下格式的数据集:

county   area    pop_2006    pop_2007    pop_2008
01001    275      1037         1052        1102
01003    394      2399         2424        2438
01005    312      1638         1647        1660

我需要这样的格式:

county    year   pop      area
01001     2006   1037      275
01001     2007   1052      275
01001     2008   1102      275
01003     2006   2399      394
01003     2007   2424      394
...

我已经尝试过我能想到的每个pivot_table,stack,unstack,wide_to_long的组合,但还没有成功。 (显然我在Python / pandas中大部分是文盲,所以请保持温和......)。

2 个答案:

答案 0 :(得分:2)

您可以使用melt进行重塑,然后使用splitvariabledrop以及sort_values。我认为您可以按astype将列year投放到int,并按subset的最后更改列顺序:

df1 = (pd.melt(df, id_vars=['county','area'], value_name='pop'))
df1[['tmp','year']] = df1.variable.str.split('_', expand=True)
df1 = df1.drop(['variable', 'tmp'],axis=1).sort_values(['county','year'])
df1['year'] = df1.year.astype(int)
df1 = df1[['county','year','pop','area']]
print (df1)
   county  year   pop  area
0    1001  2006  1037   275
3    1001  2007  1052   275
6    1001  2008  1102   275
1    1003  2006  2399   394
4    1003  2007  2424   394
7    1003  2008  2438   394
2    1005  2006  1638   312
5    1005  2007  1647   312
8    1005  2008  1660   312

print (df1.dtypes)
county    int64
year      int32
pop       int64
area      int64
dtype: object

set_indexstackreset_index的另一种解决方案:

df2 = df.set_index(['county','area']).stack().reset_index(name='pop')
df2[['tmp','year']] = df2.level_2.str.split('_', expand=True)
df2 = df2.drop(['level_2', 'tmp'],axis=1)
df2['year'] = df2.year.astype(int)
df2 = df2[['county','year','pop','area']]

print (df2)
   county  year   pop  area
0    1001  2006  1037   275
1    1001  2007  1052   275
2    1001  2008  1102   275
3    1003  2006  2399   394
4    1003  2007  2424   394
5    1003  2008  2438   394
6    1005  2006  1638   312
7    1005  2007  1647   312
8    1005  2008  1660   312

print (df2.dtypes)
county    int64
year      int32
pop       int64
area      int64
dtype: object

答案 1 :(得分:1)

正如问题标题所暗示的,我们可以使用 pd.wide_to_long:

res = pd.wide_to_long(df, stubnames="pop", i=["county", "area"], j="year", sep="_")

得到

                   pop
county area year
1001   275  2006  1037
            2007  1052
            2008  1102
1003   394  2006  2399
            2007  2424
            2008  2438
1005   312  2006  1638
            2007  1647
            2008  1660

要完全匹配问题中的输出格式,可以链接 reset_indexreindex(跨列):

>>> res.reset_index().reindex(["county", "year", "pop", "area"], axis=1)

   county  year   pop  area
0    1001  2006  1037   275
1    1001  2007  1052   275
2    1001  2008  1102   275
3    1003  2006  2399   394
4    1003  2007  2424   394
5    1003  2008  2438   394
6    1005  2006  1638   312
7    1005  2007  1647   312
8    1005  2008  1660   312