2

我想部分“折叠”一个DataFrame/matrix 并通过对压缩值求和来保持结构完整。例如,我有这个:

CHROM     POS     GENE     DESC     JOE      FRED   BILLY    SUSAN    TONY
10        1442    LOXL4    bad      1        0      0        1        0
10        335     LOXL4    bad      1        0      0        0        0
10        3438    LOXL4    good     0        0      1        0        0
10        4819    PYROXD2  bad      0        1      0        0        0
10        4829    PYROXD2  bad      0        1      0        1        0
10        9851    HPS1     good     1        0      0        0        0

前 4 列是描述符,后 4 列是人员/观察。最终目标是计算每人每个基因的“好”和“坏”观察总数。因此,我想要这个:

GENE     DESC     JOE      FRED   BILLY    SUSAN    TONY
LOXL4    bad      2        0      0        1        0
LOXL4    good     0        0      1        0        0
PYROXD2  bad      0        2      0        1        0
HPS1     good     1        0      0        0        0

以下代码折叠了所有单独的观察结果(Joe、Fred 等),我怎样才能将它们分开?我还希望足够灵活,以便将来容纳更多人(保持相同的 4 个描述符列)

mytable.groupby(['GENE','DESC']).size()
4

1 回答 1

4

只需使用 groupby 对象的聚合方法:

In [156]: df
Out[156]: 
   CHROM   POS     GENE  DESC  JOE  FRED  BILLY  SUSAN  TONY
0     10  1442    LOXL4   bad    1     0      0      1     0
1     10   335    LOXL4   bad    1     0      0      0     0
2     10  3438    LOXL4  good    0     0      1      0     0
3     10  4819  PYROXD2   bad    0     1      0      0     0
4     10  4829  PYROXD2   bad    0     1      0      1     0
5     10  9851     HPS1  good    1     0      0      0     0

In [157]: grouped = df.groupby(['GENE', 'DESC'])

In [158]: grouped.agg(np.sum) # agg is a shortcut for aggregate
Out[158]: 
              CHROM   POS  JOE  FRED  BILLY  SUSAN  TONY
GENE    DESC                                            
HPS1    good     10  9851    1     0      0      0     0
LOXL4   bad      20  1777    2     0      0      1     0
        good     10  3438    0     0      1      0     0
PYROXD2 bad      20  9648    0     2      0      1     0

正如 Daniel Velkow 在评论中提到的那样, groupby 对象具有一些用于简单聚合的“内置”方法,例如sum, mean, ... (类似于ufuncsnumpy 中的方法,可用作 numpy 数组的方法)。所以最后一步可以进一步简化为

In [159]: grouped.sum()
Out[159]: 
              CHROM   POS  JOE  FRED  BILLY  SUSAN  TONY
GENE    DESC                                            
HPS1    good     10  9851    1     0      0      0     0
LOXL4   bad      20  1777    2     0      0      1     0
        good     10  3438    0     0      1      0     0
PYROXD2 bad      20  9648    0     2      0      1     0

如果您想对每一列进行不同的操作,根据文档,您可以将 a 传递dictaggregate.

但是,我发现无法为单个列指定函数并为其他列使用默认值。所以一种方法是定义一个自定义聚合函数:

def custom_agg(s, default=np.sum, other={}):
    if s.name in other.keys():
        return other[s.name](s)
    else:
        return default(s)

而不是通过将函数和参数传递给来应用它agg

In [59]: grouped.agg(custom_agg, default=np.sum, other={'CHROM': np.mean})
Out[59]: 
              CHROM   POS  JOE  FRED  BILLY  SUSAN  TONY
GENE    DESC                                            
HPS1    good     10  9851    1     0      0      0     0
LOXL4   bad      10  1777    2     0      0      1     0
        good     10  3438    0     0      1      0     0
PYROXD2 bad      10  9648    0     2      0      1     0
于 2012-08-09T17:26:24.697 回答