使用pandas聚合所有dataframe行对组合

2024-06-14 10:51:50 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用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))可以很容易地获得基因对集,但是我无法根据它们的值来计算如何聚合特定的行。有人能建议吗?谢谢你


Tags: 数据importpandasdf基因itertoolscase2case1
2条回答

在走得太远之前,你应该记住你的数据变得非常快。对于5行,输出将是C(5,2)5+4+3+2+1等。

也就是说,我会考虑在numpy中做这个以提高速度(你可能想在你的问题中添加一个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

根据大小/速度问题,您可能需要分离字符串和数字代码,并对数字块进行矢量化。如果你的数据很大,如果数据很大,这段代码不太可能很好地扩展,这可能会决定你需要什么样的答案(也可能需要考虑如何存储结果)。

我想不出一个聪明的矢量化方法来实现这一点,但是除非性能是一个真正的瓶颈,否则我倾向于使用最简单的有意义的东西。在这种情况下,我可以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

相关问题 更多 >