【问题标题】:Python pandas to partially collapse 2d matrixPython pandas 部分折叠二维矩阵
【发布时间】:2012-08-09 17:15:40
【问题描述】:

我想部分“折叠”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()

【问题讨论】:

    标签: python grouping pivot-table pandas crosstab


    【解决方案1】:

    只需使用 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 对象有一些“内置”方法用于简单的聚合,如 summean、...(类似于 numpy 中的 ufuncs,可用作方法对于 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
    

    如果你想对每一列进行不同的操作,根据docs你可以将dict传递给aggregate

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

    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
    

    【讨论】:

    • 另外grouped.sum()grouped.agg(np.sum)的简写
    • @DanielVelkov 你是对的,谢谢,我已经更新了答案。
    • 作为后续问题,聚合时可以对每一列执行不同的操作吗?例如,如果我想对给定的最后 5 列求和,但取“CHROM”列的平均值而不是对这些值求和?
    • @alexhli 我更新了我的答案。通常传递一个字典就足够了,但你必须命名所有列。如果您想要其余列的默认值,我认为您需要一个自定义函数。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-23
    • 1970-01-01
    • 2017-12-22
    • 1970-01-01
    • 1970-01-01
    • 2017-03-23
    • 1970-01-01
    相关资源
    最近更新 更多