用Python替换数千行ID名称的最佳方法是什么?

3
我有两个数据集。一个包含16169行5列,我想用另一个数据集中对应的名称替换其中一列。这些对应的名称来自另一个数据集。
例如:
UniProtID NAME Q15173 PPP2R5B P30154 PPP2R1B P63151 PPP2R2A
DrugBankID Name Type UniProtID UniProt Name DB00001 Lepirudin BiotechDrug P00734 Prothrombin DB00002 Cetuximab BiotechDrug P00533 Epidermal growth factor receptor DB00002 Cetuximab BiotechDrug O75015 Low affinity immunoglobulin gamma Fc region receptor III-B
在这个例子中,我想用上面数据集示例中的相应名称替换所有的UniProt ID。最好的方法是什么?
我真的很新编程和Python,所以任何建议和帮助都将不胜感激。

这些数据集是以制表符分隔的吗?你会使用像 pandas 这样的模块还是更倾向于使用纯 Python? - zwer
抱歉、制表符分隔和pandas - hsy_99
2个回答

3

我认为你需要使用由set_index创建的Series进行map操作,如果一些值不匹配,则获得NaN

#change data for match
print (df1)
  UniProtID     NAME
0    O75015  PPP2R5B
1    P00734  PPP2R1B
2    P63151  PPP2R2A

df2['UniProt Name'] = df2['UniProtID'].map(df1.set_index('UniProtID')['NAME'])
print (df2)
  DrugBankID       Name         Type UniProtID UniProt Name
0    DB00001  Lepirudin  BiotechDrug    P00734      PPP2R1B
1    DB00002  Cetuximab  BiotechDrug    P00533          NaN
2    DB00002  Cetuximab  BiotechDrug    O75015      PPP2R5B

如果需要保留原始值而非NaN:
df2['UniProt Name'] = df2['UniProtID'].map(df1.set_index('UniProtID')['NAME'])
                                      .fillna(df2['UniProt Name'])
print (df2)
  DrugBankID       Name         Type UniProtID  \
0    DB00001  Lepirudin  BiotechDrug    P00734   
1    DB00002  Cetuximab  BiotechDrug    P00533   
2    DB00002  Cetuximab  BiotechDrug    O75015   

                       UniProt Name  
0                           PPP2R1B  
1  Epidermal growth factor receptor  
2                           PPP2R5B  

使用 merge 解决方案 - 需要进行 left 连接,并使用 fillnacombine_first 进行处理,最后通过 drop 移除列:

df = pd.merge(df2, df1, on="UniProtID", how='left')
df['UniProt Name'] = df['NAME'].fillna(df['UniProt Name'])
#alternative
#df['UniProt Name'] = df['NAME'].combine_first(df['UniProt Name'])
df.drop('NAME', axis=1, inplace=True)
print (df)
  DrugBankID       Name         Type UniProtID  \
0    DB00001  Lepirudin  BiotechDrug    P00734   
1    DB00002  Cetuximab  BiotechDrug    P00533   
2    DB00002  Cetuximab  BiotechDrug    O75015   

                       UniProt Name  
0                           PPP2R1B  
1  Epidermal growth factor receptor  
2                           PPP2R5B  

df = pd.merge(df2, df1, on="UniProtID", how='left')
df = df.drop('UniProt Name', axis=1).rename(columns={'NAME':'UniProt Name'})
print (df)
  DrugBankID       Name         Type UniProtID UniProt Name
0    DB00001  Lepirudin  BiotechDrug    P00734      PPP2R1B
1    DB00002  Cetuximab  BiotechDrug    P00533          NaN
2    DB00002  Cetuximab  BiotechDrug    O75015      PPP2R5B

谢谢!我会试一下 :) - hsy_99

0

解决这个问题的更一般方法是在两个表上执行类似于SQL的连接。

注意:对于较大的数据集,这可能会很昂贵,我没有进行性能实验。

import pandas as pd

left = pd.DataFrame({"UniProtID": ["Q15173", "P30154", "P63151"],
                     "Name": ["PPP2R5B", "PPP2R1B", "PPP2R2A"]})

right = pd.DataFrame({"UniProtID": ["Q15173", "P30154", "P63151"],
                      "UniProt Name": ["Prothrombin", "Epidermal growth factor receptor", "Low affinity immunoglobulin gamma Fc region receptor III-B"],
                      "Type": ["BiotechDrug", "BiotechDrug", "BiotechDrug"],
                      "DrugBankID": ["DB00001", "DB00002", "DB00003"]})

result = pd.merge(left, right, on="UniProtID")

参考资料:https://pandas.pydata.org/pandas-docs/stable/merging.html#overlapping-value-columns


谢谢!如果它很贵的话,我肯定没有预算。但我会看看 :) - hsy_99

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接