簡體   English   中英

計算值並將其放入MultiIndex Pandas DataFrame中的第二級列

[英]Calculating and placing values into a second level column in a MultiIndex Pandas DataFrame

我有一個多索引的DataFrame,我想在其中放置一個名為AB的二級列。 此二級色譜柱的值應等於每個樣品的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)

此代碼生成以下輸入文件/ 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

期望的結果應該是:

      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

我已經提出了一個解決方案,但它很慢,效率低,依賴於循環。 我需要一個更有效的解決方案,因為我將在非常大的文件上執行此操作。

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) 

任何幫助都將受到高度贊賞。

您需要重新組織索引以確保只有一個名為“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 

現在計算新列是微不足道的:

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

如果需要,可以將索引恢復為之前的狀態。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM