从DataFrame堆叠时命名Pandas系列

时间:2014-03-13 16:03:28

标签: python pandas

我在pandas中的一个常见工作流程是从" wide"中获取某些数字函数的数据。形成并将其变成一个长长的"用于绘图和统计建模的表格数据框。

我的意思是宽泛的形式是列中有可变信息编码。例如,假设我在10个不同科目的5个时间点的每个时间点测量了一些值:

wide_df = pd.DataFrame(np.random.randn(10, 5),
                       index=pd.Series(list("abcdefghij"), name="subject"),
                       columns=pd.Series(np.arange(5) * 2, name="timepoint"))
print wide_df


timepoint         0         2         4         6         8
subject                                                    
a         -0.670881  0.959608 -0.480081  0.142092  1.697058
b          2.369493 -0.561081 -0.183635 -0.807523 -0.421347
c         -0.908420  0.629171  0.196728 -0.907443  0.264352
d         -0.390138 -1.821304 -1.994605  0.225164  0.187649
e         -0.860542 -0.998323 -0.490968 -0.815570 -1.009524
f         -0.917390 -0.120567 -0.893095 -0.359155 -0.204112
g          0.557500 -1.522631 -1.175746  0.705043 -0.366932
h         -0.817043  2.204493 -0.305202  0.464969  0.280027
i         -1.137253  0.350984  0.095577  0.468167 -0.058058
j         -0.569986  2.438580 -0.514894  0.860504  1.397393

[10 rows x 5 columns]

我知道如何将此内容与长格式数据框架纠缠在一起的最快方式是使用stack然后使用reset_index

long_df = wide_df.stack().reset_index()
print long_df.head()

 subject  timepoint         0
0       a          0 -0.670881
1       a          2  0.959608
2       a          4 -0.480081
3       a          6  0.142092
4       a          8  1.697058

[5 rows x 3 columns]

问题是我的"值"列现在名为0。我能做到

long_series = wide_df.stack()
long_series.name = "value"
long_df = long_series.reset_index()

但是更多的输入,需要命名一个中间变量,并将方法调用与属性赋值混合在一起,真正打破了我的流程。

有没有办法在一行中执行此操作?我想也许df.stack可能需要name个参数,但它没有,Series个对象似乎没有set_name方法可以找到。

我确实知道pandas.melt,但在这种情况下看起来有点过分"纯粹的"宽表数据,它删除了重要的subject索引。这里有另一个答案吗?

1 个答案:

答案 0 :(得分:5)

出于这个原因,它们是Series.reset_index的name参数

In [14]: wide_df.stack().reset_index(name='foo')
Out[14]: 
   subject  timepoint       foo
0        a          0 -0.179968
1        a          2  1.559283
2        a          4  1.020142
3        a          6 -0.899663
4        a          8  2.983990
5        b          0  0.586476
6        b          2  0.055108
7        b          4  1.834005
8        b          6  1.226371
9        b          8  0.953103
10       c          0 -0.919273

如果您愿意,也可以定义它(并且可以很好地添加到DataFrame中):

In [14]: def _melt(self, *args, **kwargs):
   ....:     return pd.melt(self.reset_index(), *args, **kwargs)
   ....: 

In [15]: DataFrame.melt = _melt

In [19]: wide_df.melt('subject',value_name='foo')
Out[19]: 
   subject  timepoint       foo
0        a          0  0.374912
1        b          0 -0.016272
2        c          0 -0.510553
3        d          0 -1.532472
4        e          0 -0.115107
5        f          0 -0.101772
6        g          0 -0.020966
7        h          0  0.427469