pandas df:添加列(如果不存在),将值从dict添加到新列

时间:2018-07-26 19:44:03

标签: python-3.x pandas dataframe

我是熊猫新手,但是我试图创建一个大型数据框,在其中我通过其序列ID(Seq_ID)组织有关许多序列的信息,并将有关序列的信息添加到数据框中。 当前df看起来像这样:

     Seq_ID        mol_type
0 4_cDNA_v              RNA
1 2_133+_v              RNA
2 5_BM4D_g              RNA
.                         .
.                         .
1301 4_PB_g             RNA

我想编写一个查看当前df的函数source_df,如果“ Seq_source”列不存在,则将其添加。 然后填写“ Seq_Source”列,我有一系列称为cell_type的key:value对。我想搜索Seq_ID列以查看是否在Seq_ID中找到任何值,如果是,则在新列'Seq_Source'的相应行中添加键,使其看起来像以下内容:

     Seq_ID    mol_type    Seq_Source
0 4_cDNA_v          RNA            PB
1 2_133+_v          RNA          HSPC
2 5_BM4D_g          RNA          BMMC
.                     
.                     
1301 4_CD4_g        RNA          PBMC

我写了一些伪代码来帮助解释我对这种方法的想法。

cell_type = {
    'PBMC':['CD4','NK', 'CD8'],
    'HSPC': ['133+', '133+F'],
    'PB': ['cDNA', 'cDNAA', 'cDNAB', 'cDNAC'],
    'BMMC':['cDNABM', '34D_Vc','BM4_Vs', 'BM4_Vc', 'BM4n_Vs']
        }


def find_cell_source(dictionary, df, reference, new_header):
    '''
    takes in a dictionary where key corresponds to list of values.
    If new_header does not exist, the new column is created.
    If a value from key:value pair is found within any of the string entries under reference column
    in the database, key is added to reference row under new_header.
    '''

    # add new_header if does not exist
    df[new_header] = [df[new_header] if new_header not in df]

    # read rows of reference column and see if values from dict is in references
    # add key to row under new_header if it exists, pass if it doesn't

    for i in df['reference']:
        for k,v in dictionary:
            for j in v:
                if j in i:
                    df['new_header'] = k
                else:
                    pass
    return df


find_cell_source(cell_type, source_df, 'Seq_ID', 'Seq_Source')

2 个答案:

答案 0 :(得分:2)

您可以通过各种方式获取Seq_ID的相关部分,在这种情况下,您似乎可以只使用.str.split,然后映射值。如果在regex上进行拆分还不够,请使用_

d = dict((k,v) for v, x in cell_type.items() for k in x)
df['Seq_Source'] = df.Seq_ID.str.split('_', expand=True)[1].map(d)

输出:

        Seq_ID mol_type Seq_Source
0     4_cDNA_v      RNA         PB
1     2_133+_v      RNA       HSPC
2     5_BM4D_g      RNA        NaN
1301   4_CD4_g      RNA       PBMC

请注意,由于BM4D不在cell_type的任何列表中,因此它被映射到NaN

答案 1 :(得分:2)

每当您发现自己经常需要查找一个值以恢复密钥时,通常最好重塑该词典以允许您通过密钥进行查找,这更有效。

假设内部列表中的所有值都是唯一的,则可以使用以下代码段重塑查找字典:

cell_type_reshaped = {}

for k, v in cell_type.items():
    for element in v:
        cell_type_reshaped[element] = k

给予:

{'133+': 'HSPC',
 '133+F': 'HSPC',
 '34D_Vc': 'BMMC',
 'BM4_Vc': 'BMMC',
 'BM4_Vs': 'BMMC',
 'BM4n_Vs': 'BMMC',
 'CD4': 'PBMC',
 'CD8': 'PBMC',
 'NK': 'PBMC',
 'cDNA': 'PB',
 'cDNAA': 'PB',
 'cDNAB': 'PB',
 'cDNABM': 'BMMC',
 'cDNAC': 'PB'}

创建一个小的DataFrame进行测试:

df = pd.DataFrame(data=[['4_cDNA_v', 'RNA'], ['2_133+_v', 'RNA'], 
                        ['5_BM4D_g', 'RNA']], columns=['Seq_ID', 'mol_type'])

从这里开始,这只是使用Pandas地图功能查找字典的一种情况。请注意,这里还有一个附加步骤,可对Seq_ID进行切片,以从包含字符串的最后一个字符开始将第3个字符转换为第3个字符,这似乎是它们遵循的模式。如果不是这种情况,请告诉我,我可以进行更新。

df['Seq_Source'] = df['Seq_ID'].str.slice(2, -2).map(cell_type_reshaped)

给出我认为至少接近您期望的结果的

     Seq_ID mol_type Seq_Source
0  4_cDNA_v      RNA         PB
1  2_133+_v      RNA       HSPC
2  5_BM4D_g      RNA        NaN

在您的示例中,我看到您有到BMMC的5_BM4D_g映射,我不确定其背后的逻辑,因此请发表评论,我可以进行更新。