如何将pandas数据聚合成平面数据帧(没有分层索引)?

时间:2016-03-31 17:30:28

标签: python pandas dataframe

我有两个时间值的重复测量数据:

name    t   value   replicate
foo 1   0.5 a
foo 1   0.55    b
foo 1   0.6 c
foo 2   0.7 a
foo 2   0.71    b
foo 2   0.72    c
bar 1   0.1 a
bar 1   0.12    b
bar 1   0.3 c
bar 2   0.4 a
bar 2   0.45    b
bar 2   0.44    c

我想将其解析为数据框并获得每个时间点(" t"列)和每个样本(" name"列)的重复项的均值和标准差。这可以通过以下方式完成:

df = pandas.read_table("data.txt",sep="\t")
g = df.groupby(["name", "t"])
new_df = g.agg([np.mean, np.std])

问题是new_df层次结构索引:

           value          
            mean       std
name t                    
bar  1  0.173333  0.110151
     2  0.430000  0.026458
foo  1  0.550000  0.050000
     2  0.710000  0.010000

如果平均值和标准值只是常规列,我怎样才能得到平面数据框?我试过了reset_index()但是没有这样做:

>>> new_df.reset_index()
  name  t     value          
               mean       std
0  bar  1  0.173333  0.110151
1  bar  2  0.430000  0.026458
2  foo  1  0.550000  0.050000
3  foo  2  0.710000  0.010000

我希望最终的数据框包含以下列:sample, t, mean, std(或value_mean, value_std)。怎么能在熊猫里做到这一点?

2 个答案:

答案 0 :(得分:3)

我会做一些与MaxU略有不同的事情。尝试将索引重置为特定列级别,然后删除其他列级别。

In [5]: new_df2 = new_df.copy()

In [6]: new_df2 = new_df2.reset_index(col_level=1)

In [7]: new_df2.columns = new_df2.columns.get_level_values(1) # same level=1

In [8]: new_df2
Out[8]: 
  name  t      mean       std
0  bar  1  0.173333  0.110151
1  bar  2  0.430000  0.026458
2  foo  1  0.550000  0.050000
3  foo  2  0.710000  0.010000

编辑:

使用MultiIndex s,可用于设置索引(垂直列)或列标签(您的案例)的多级排列,列标签存储为levels和他们的职位存储为labels。像这样:

In [4]: df.columns
Out[4]: 
MultiIndex(levels=[[u'value'], [u'mean', u'std']],
           labels=[[0, 0], [0, 1]])

通过reset_index(col_level=1),我们将MultiIndex转换为

In [5]: df.reset_index(col_level=1).columns
Out[5]: 
MultiIndex(levels=[[u'value', u''], [u'mean', u'std', u't', u'name']],
           labels=[[1, 1, 0, 0], [3, 2, 0, 1]])

将标签从索引中取出并将它们放入MultiIndex列的级别1(第二级/更低级别)。然后columns = columns.get_level_values(1)抓取级别1的列标签值,并仅将这些值设置为列标签,从而有效地降低级别0.

 Out[6]: Index([u'name', u't', u'mean', u'std'], dtype='object')

答案 1 :(得分:2)

尝试重命名列:

In [9]: new_df.reset_index(inplace=True)

让我们按以下方式设置列名:如果{列}存在,请选择level==1列,否则使用level==0

In [14]: new_df.columns = [c[1] if c[1] else c[0] for c in new_df.columns.tolist()]

In [15]: new_df
Out[15]:
  name  t      mean       std
0  bar  1  0.173333  0.110151
1  bar  2  0.430000  0.026458
2  foo  1  0.550000  0.050000
3  foo  2  0.710000  0.010000