使用pandas聚合所有数据帧行对组合

时间:2015-04-21 16:11:57

标签: python pandas aggregate combinations itertools

我使用python pandas跨数据帧执行分组和聚合,但我现在想执行特定的行成对聚合(n选择2,统计组合)。这是示例数据,我想在[mygenes]中查看所有基因对:

import pandas
import itertools

mygenes=['ABC1', 'ABC2', 'ABC3', 'ABC4']

df = pandas.DataFrame({'Gene' : ['ABC1', 'ABC2', 'ABC3', 'ABC4','ABC5'],
                       'case1'   : [0,1,1,0,0],
                       'case2'   : [1,1,1,0,1],
                       'control1':[0,0,1,1,1],
                       'control2':[1,0,0,1,0] })
>>> df
   Gene  case1  case2  control1  control2
0  ABC1      0      1         0         1
1  ABC2      1      1         0         0
2  ABC3      1      1         1         0
3  ABC4      0      0         1         1
4  ABC5      0      1         1         0

最终产品应该如下所示(默认情况下应用np.sum很好):

                 case1    case2    control1    control2
'ABC1', 'ABC2'    1         2         0            1
'ABC1', 'ABC3'    1         2         1            1
'ABC1', 'ABC4'    0         1         1            2
'ABC2', 'ABC3'    2         2         1            0
'ABC2', 'ABC4'    1         1         1            1
'ABC3', 'ABC4'    1         1         2            1 

使用itertools($ itertools.combinations(mygenes, 2))可以很容易地获得一组基因对,但我无法弄清楚如何根据它们的值执行特定行的聚合。任何人都可以建议吗?谢谢

2 个答案:

答案 0 :(得分:6)

我想不出一个聪明的矢量化方法来做到这一点,但除非性能是一个真正的瓶颈,否则我倾向于使用最简单的事情。在这种情况下,我可以set_index("Gene")然后使用loc来挑选行:

>>> df = df.set_index("Gene")
>>> cc = list(combinations(mygenes,2))
>>> out = pd.DataFrame([df.loc[c,:].sum() for c in cc], index=cc)
>>> out
              case1  case2  control1  control2
(ABC1, ABC2)      1      2         0         1
(ABC1, ABC3)      1      2         1         1
(ABC1, ABC4)      0      1         1         2
(ABC2, ABC3)      2      2         1         0
(ABC2, ABC4)      1      1         1         1
(ABC3, ABC4)      1      1         2         1

答案 1 :(得分:2)

在走得太远之前,你应该记住你的数据变得非常快。如果有5行,则输出为C(5,2)5+4+3+2+1,依此类推。

那就是说,我想考虑在速度上做这个(你可能想要为你的问题添加一个numpy标签顺便说一下)。无论如何,这不像它可能的那样矢量化,但至少应该是一个开始:

df2 = df.set_index('Gene').loc[mygenes].reset_index()

import math
sz = len(df2)
sz2 = math.factorial(sz) / ( math.factorial(sz-2) * 2 )

Gene = df2['Gene'].tolist()
abc = df2.ix[:,1:].values

import math
arr = np.zeros([sz2,4])
gene2 = []
k = 0

for i in range(sz):
    for j in range(sz):
        if i != j and i < j:
            gene2.append( gene[i] + gene[j] )
            arr[k] = abc[i] + abc[j]
            k += 1

pd.concat( [ pd.DataFrame(gene2), pd.DataFrame(arr) ], axis=1 )
Out[1780]: 
          0  0  1  2  3
0  ABC1ABC2  1  2  0  1
1  ABC1ABC3  1  2  1  1
2  ABC1ABC4  0  1  1  2
3  ABC2ABC3  2  2  1  0
4  ABC2ABC4  1  1  1  1
5  ABC3ABC4  1  1  2  1

根据尺寸/速度问题,您可能需要将字符串和数字代码分开并对数字部分进行矢量化。如果你的数据很大,这个代码不太可能扩展得很好,如果是,那可能决定你需要什么样的答案(也可能需要考虑如何存储结果)。