【问题标题】:How to iterate over dfs and append data with combine names如何迭代 dfs 并使用组合名称附加数据
【发布时间】:2019-06-11 12:29:31
【问题描述】:

我有这个问题要解决,这是上一个问题How to iterate over pandas df with a def function variable function 的延续,并且给定的答案非常有效,但现在我必须将所有数据附加到 2 列数据框中(加合物名称和质量)。

这是来自上一个问题:

我的目标:我必须计算给定“化合物”的“加合物”,两者都代表 numbes,但对于每个“化合物”,有 46 种不同的“加合物”。

每个加合物的计算如下:

加合物 1 = [精确质量*M/电荷 + 加合物质量]

其中,exact_mass = 数字,M 和 Charge = 根据每种加合物类型的数字(1、2、3 等),Adduct_mass = 根据每种加合物的数字(正数或负数)。

我的数据:2 个数据帧。一个带有加合物名称、M、Charge、Addduct_mass。另一个对应于我要迭代的化合物的 Compound_name 和 Exact_mass(我只是放了一个小数据集)

加合物:df_al

import pandas as pd 
data = [["M+3H", 3, 1, 1.007276], ["M+3Na", 3, 1, 22.989], ["M+H", 1, 1, 
1.007276], ["2M+H", 1, 2, 1.007276], ["M-3H", 3, 1, -1.007276]]
df_al = pd.DataFrame(data, columns=["Ion_name", "Charge", "M", "Adduct_mass"])

化合物:df

import pandas as pd 
data1 = [[1, "C3H64O7", 596.465179], [2, "C30H42O7", 514.293038], [4, 
"C44H56O8", 712.397498], [4, "C24H32O6S", 448.191949], [5, "C20H28O3", 
316.203834]]
df = pd.DataFrame(data1, columns=["CdId", "Formula", "exact_mass"])

这个问题的解决方法是:

df_name = df_al["Ion_name"]
df_mass = df_al["Adduct_mass"]
df_div = df_al["Charge"]
df_M = df_al["M"]
#Defining general function 
def Adduct(x,i):
    return x*df_M[i]/df_div[i] + df_mass[i]

#Applying general function in a range from 0 to 5. 
for i in range(5):
    df[df_name.loc[i]] = df['exact_mass'].map(lambda x: Adduct(x,i))

输出

    Name exact_mass  M+3H       M+3Na        M+H        2M+H        M-3H
0   a   596.465179  199.829002  221.810726  597.472455  1193.937634 197.814450
1   b   514.293038  172.438289  194.420013  515.300314  1029.593352 170.423737
2   c   712.397498  238.473109  260.454833  713.404774  1425.802272 236.458557
3   d   448.191949  150.404592  172.386316  449.199225  897.391174  148.390040
4   e   316.203834  106.408554  128.390278  317.211110  633.414944  104.39400

现在这是正确的计算,但我现在需要一个文件,其中: - 仅存在 2 列(名称和质量) -所有不同的加合物一个接一个地附加

想要的输出

 Name     Mass 
 a_M+3H  199.82902
 a_M+3Na 221.810726
 a_M+H   597.472455
 a_2M+H  1193.937634
 a_M-3H  197.814450 
 b_M+3H  514.293038
 .
 . 
 .
 c_M+3H

等等。

我还需要将各个化合物的名称与离子形式(M+3H、M+H 等)结合起来。

此时我没有代码。

我会从一开始就感谢任何建议和更好的方法。


这部分是对上述问题的更新:

可以像这样获取和输出:

  Name     Mass       RT
 a_M+3H  199.82902     1
 a_M+3Na 221.810726    1
 a_M+H   597.472455    1
 a_2M+H  1193.937634   1
 a_M-3H  197.814450    1
 b_M+3H  514.293038    3
 .           
 . 
 .
 c_M+3H                2

所有形式的化合物的 RT 值相同,在本例中为 a =1、b = 3、c =2 等的 RT。

是否可以从数据集 df(我在下面更新)中合并(保留此列)?如您所见,df 有更多列,如“公式”和“RT”,它们在计算后消失。

import pandas as pd 
data1 = [[a, "C3H64O7", 596.465179, 1], [b, "C30H42O7", 514.293038, 3], [c, 
"C44H56O8", 712.397498, 2], [d, "C24H32O6S", 448.191949, 4], [e, "C20H28O3", 
316.203834, 1.5]]
df = pd.DataFrame(data1, columns=["Name", "Formula", "exact_mass", "RT"])  

第三部分! (对不起,谢谢)

这是我使用下面的代码在一个小数据集 (df) 上进行的试验,与上面的 df_al 相同。

df=

代码

#Defining variables for calculation

df_name = df_al["Ion_name"]
df_mass = df_al["Adduct_mass"]
df_div = df_al["Charge"]
df_M = df_al["M"]
df_ID= df["Name"]

#Defining the RT dictionary

RT = dict(zip(df["Name"], df["RT"]))

#Removing RT column

df=df.drop(columns=["RT"])

#Defining general function 

def Adduct(x,i):
    return x*df_M[i]/df_div[i] + df_mass[i]

#Applying general function in a range from 0 to 46. 

for i in range(47):
    df[df_name.loc[i]] = df['exact_mass'].map(lambda x: Adduct(x,i)) 

df 

输出

#Melting

df = pd.melt(df, id_vars=['Name'], var_name = "Adduct", value_name= "Exact_mass", value_vars=[x for x in df.columns if 'Name' not in x and 'exact' not in x])

df['name'] = df.apply(lambda x:x[0] + "_" + x[1], axis=1)

df['RT'] = df.Name.apply(lambda x: RT[x[0]] if x[0] in RT else np.nan)

del df['Name']

del df['Adduct']

df['RT'] = df.name.apply(lambda x: RT[x[0]] if x[0] in RT else np.nan)

df

输出

为什么是 NaN?

【问题讨论】:

    标签: python-3.x pandas slice


    【解决方案1】:

    这就是我的做法,pandas.melt 来拯救:

    import pandas as pd
    import numpy as np
    
    from io import StringIO
    
    s = StringIO('''
        Name exact_mass  M+3H       M+3Na        M+H        2M+H        M-3H
    0   a   596.465179  199.829002  221.810726  597.472455  1193.937634 197.814450
    1   b   514.293038  172.438289  194.420013  515.300314  1029.593352 170.423737
    2   c   712.397498  238.473109  260.454833  713.404774  1425.802272 236.458557
    3   d   448.191949  150.404592  172.386316  449.199225  897.391174  148.390040
    4   e   316.203834  106.408554  128.390278  317.211110  633.414944  104.39400
    ''')
    
    df = pd.read_csv(s, sep="\s+")
    
    df = pd.melt(df, id_vars=['Name'], value_vars=[x for x in df.columns if 'Name' not in x and 'exact' not in x])
    
    
    
    df['name'] = df.apply(lambda x:x[0] + "_" + x[1], axis=1)
    
    del df['Name']
    del df['variable']
    
    
    RT = {'a':1, 'b':2, 'c':3, 'd':5, 'e':1.5}
    
    df['RT'] = df.name.apply(lambda x: RT[x[0]] if x[0] in RT else np.nan)
    df
    

    这是输出:

    【讨论】:

    • 问题!这只是真实 df 的一些数据,在这种情况下 value_vars 只是 46 中的 5 个(整个数据),我应该一一输入吗?
    • 不,让我修改以获取所有列。两分钟
    • 亲爱的@PankajJoshi,如果在熔化之前的 df 中存在我想保留的列,例如分子式 (srt),我该怎么做?
    • 能否请您将此添加到您的问题中,并举例说明,这样会更清楚。
    • @PanjakJoshi 我刚刚更新完问题!亲切的问候
    猜你喜欢
    • 2021-12-30
    • 1970-01-01
    • 2016-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-25
    • 2014-03-27
    相关资源
    最近更新 更多