【问题标题】:Replace values of a DataFrame with values of a dictionary用字典的值替换 DataFrame 的值
【发布时间】:2021-10-16 03:38:44
【问题描述】:

我有 两个 DataFrames 有数千行。这些列都有 dtype 字符串。一个 sn-p 看起来像这样:

DF1:

                 ID   SUCCESSOR 
    0       0001234     3620031
    1       0001235     6640002
    2       0002456     8620003
    3       0013456     8640004
    4       1711999     1283456 <- see DF2
    ...         ...         ... 
    409813  9162467        <NA>
    409814  9212466        <NA>
    409815  9312466     6975A0C
    409816  9452463        <NA>
    409817  9591227        <NA>

DF2:

                 ID
    2       1111682
    3       1123704
    14      1567828
    15      1711999 <- that value should be replaced with '1283456'
    16      1711834
    ...         ...
    845775  970879B
    845776  975879B
    845777  9275A0A
    845778  9285A05
    845779  9295A05

不要对第二个 DataFrame 缺少一些索引感到惊讶,因为我之前过滤了它们,因为它们不相关。此外,NaN 不相关,因为我的算法绕过了它们。

我现在想用第一个 DataFrame 中具有相同 ID 的后继者替换第二个 DataFrame 中的 ID。

输出应该是:

                 ID
    2       1111682
    3       1123704
    14      1567828
    15      1283456 <- now replaced
    16      1711834
    ...         ...
    845775  970879B
    845776  975879B
    845777  9275A0A
    845778  9285A05
    845779  9295A05

为了不炸毁这个例子,我只替换了一个值。实际上有几个替代品

两种方法:

  1. 在我的第一个方法中,我迭代了 DF1 并使用了 replace() 函数,但是这种方法需要数年时间,因此它没有用。

  2. 在我的第二种方法中,我首先将 DF1 转换为字典,然后应用 map() 函数。我按照 JohnE 的描述执行此操作:Remap values in pandas column with a dict 在一个小例子中,它的效果非常好:

     df = pd.DataFrame({'col1': {1: 1, 2: 2, 3: 4, 4: 1}, 'col2': {1: 2, 2: np.nan}})
     di = {1: "A", 2: "B"}
    
     col1  col2
     1     1   2.0
     2     2   NaN
     3     4   NaN
     4     1   NaN
    
     df['col1'].map(di).fillna(df['col1'])
    
     1    A
     2    B
     3    4
     4    A
    

我映射 DF1 和 DF2 的函数如下所示:

    def mapping(df1, df2):   

        di =dict(zip(df1.ID, df1.SUCCESSOR)) # create the dict
        changes = 1   

        while(changes > 0):        
    
            changes = 0
            df_old = df2                    
            print(df2) #check how df2 looks before mapping.
            df2['ID'] = df2['ID'].map(di).fillna(df2['ID'])                   
            print(df2) # check how df2 looks after mapping. Unfortunately no changes :( so the error must be in the mapping function one line above here.
            if df_old.equals(df2) == False:
                changes = 1    
    
        return df2

那么显然错误一定在这一行:

    df2['ID'] = df2['ID'].map(dic).fillna(df2['ID']).

但是,我就是不明白为什么这不起作用。什么在这里不起作用,为什么?

如果有人能帮助我,我永远感激他们!!!

最好的问候, 阿方索

编辑: 编辑: 我发现了错误,我是个白痴。 我的解决方案有效,但行:“df_old = df2”阻止了循环继续。无论如何,非常感谢,如果我抢了时间,对不起!

【问题讨论】:

    标签: python pandas dataframe dictionary replace


    【解决方案1】:

    这是一个通过过滤数据帧来创建替换字典的单行器:

    df2['ID'] = df2['ID'].replace(dict(zip(df2[df2['ID'].isin(df1['ID'])].sort_values(by=['ID']).reset_index()['ID'], df1.loc[df1['ID'].isin(df2['ID'])].sort_values(by=['ID']).reset_index()['SUCCESSOR'])))
    

    【讨论】:

    • 谢谢,但即使是这个解决方案也不会改变 DF2 中的任何内容。我不知道问题是什么。会不会是函数不适用于子集? DF2 是原始的子集。它最初有大约 845k 个 ID,但过滤后只剩下大约 490k 个 ID,因此索引中存在空白。
    • 另外,我必须补充一点,DF2 中的 ID 有时最多有 30 个后继 ID。 DF1 解释了 ID 的替代,即如果在 DF2 中交换了 ID,则很可能在下一次迭代中必须再次交换它们。直到所有 ID 都达到其“最后继任者”为止。这就是我在第一篇文章中使用 while 循环的原因。迭代继续进行,直到不再需要交换 ID,因为 DF1 中没有更多的继任者。
    最近更新 更多