我使用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)
)可以很容易地获得一组基因对,但我无法弄清楚如何根据它们的值执行特定行的聚合。任何人都可以建议吗?谢谢
答案 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
根据尺寸/速度问题,您可能需要将字符串和数字代码分开并对数字部分进行矢量化。如果你的数据很大,这个代码不太可能扩展得很好,如果是,那可能决定你需要什么样的答案(也可能需要考虑如何存储结果)。