[英]Calculating and placing values into a second level column in a MultiIndex Pandas DataFrame
I have a multi-indexed DataFrame in which I want to place a level two column named AB. 我有一个多索引的DataFrame,我想在其中放置一个名为AB的二级列。 The values of this level two column should equal the AD[1]/DP for each Sample eg Sample1 AB = 60/180 此二级色谱柱的值应等于每个样品的AD [1] / DP,例如Sample1 AB = 60/180
import pandas as pd
import numpy as np
genotype_data = [
['0/1', '120,60', 180, 5, '0/1', '200,2', 202, 99],
['0/1', '200,20', 60, 99, '0/1', '200,50', 250, 99],
['0/1', '200,2', 202, 99, '0/1', '200,2', 202, 99]
]
genotype_columns = [['Sample1', 'Sample2'], ['GT', 'AD', 'DP', 'GQ']]
cols = pd.MultiIndex.from_product(genotype_columns)
df = pd.DataFrame(data=genotype_data, columns=cols)
This code produces the following input file/df: 此代码生成以下输入文件/ df:
Sample1 Sample2
GT AD DP GQ GT AD DP GQ
0/1 120,60 180 5 0/1 200,2 202 99
0/1 200,20 60 3 0/1 200,50 250 99
0/1 200,2 202 99 0/1 200,2 202 99
The desired result should be: 期望的结果应该是:
Sample1 Sample2
GT AD DP GQ AB GT AD DP GQ AB
0/1 120,60 180 5 0.33 0/1 200,2 202 99 0.01
0/1 200,20 60 3 0.33 0/1 200,50 250 99 0.20
0/1 200,2 202 99 0.01 0/1 200,2 202 99 0.01
I have come up with a solution to this but it is pretty slow, inefficient and relies on loops. 我已经提出了一个解决方案,但它很慢,效率低,依赖于循环。 I need a much more efficient solution as I will be performing this on very big files. 我需要一个更有效的解决方案,因为我将在非常大的文件上执行此操作。
def calc_AB(df):
sam = df.columns.levels[0][0]
AD = df.xs('AD', level=1, axis=1).unstack().str.split(",", n=2)
DP = df.xs('DP', level=1, axis=1).unstack()
AB = round(pd.to_numeric(AD.str[1]) / pd.to_numeric(DP), 2)
df[sam, 'AB'] = AB.tolist()
return df
dfs = [calc_AB(df[[sam]].astype(str)) for sam in df.columns.levels[0].tolist()]
pd.concat(dfs, axis=1)
Any help with this would be highly appreciated. 任何帮助都将受到高度赞赏。
You need to reorganize the indexes to make sure that there is only one column called 'AD': 您需要重新组织索引以确保只有一个名为“AD”的列:
df.columns = df.columns.swaplevel(0,1)
stacked = df.stack()
# AD DP GQ GT
#0 Sample1 120,60 180 5 0/1
# Sample2 200,2 202 99 0/1
#1 Sample1 200,20 60 99 0/1
# Sample2 200,50 250 99 0/1
#2 Sample1 200,2 202 99 0/1
# Sample2 200,2 202 99 0/1
Calculating the new column now is trivial: 现在计算新列是微不足道的:
stacked['AB'] = stacked['AD'].str.split(',').str[1].astype(int)/stacked['DP']
stacked
# AD DP GQ GT AB
#0 Sample1 120,60 180 5 0/1 0.333333
# Sample2 200,2 202 99 0/1 0.009901
#1 Sample1 200,20 60 99 0/1 0.333333
# Sample2 200,50 250 99 0/1 0.200000
#2 Sample1 200,2 202 99 0/1 0.009901
# Sample2 200,2 202 99 0/1 0.009901
You can restore the indexes to whatever they were before if you want. 如果需要,可以将索引恢复为之前的状态。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.