【问题标题】:Replacing values in a dataframe from another dataframe从另一个数据框中替换数据框中的值
【发布时间】:2019-05-09 20:26:36
【问题描述】:

所以我正在使用具有两个数据框的数据集。 数据框如下所示:

df1:

Item_ID  Item_Name
0        A
1        B
2        C

df2:

Item_slot_1   Item_slot_2  Item_Slot_3
2             2            1
1             2            0
0             1            1

df2 中的值表示来自 df1 的 Item_ID。如何将 df2 中的值从 item_id 替换为实际的项目名称,以便 df2 看起来像:

Item_slot_1   Item_slot_2  Item_Slot_3
C             C            B
B             C            A
A             B            B

现实中的数据集要大得多,并且有更多的 id 和名称,而不仅仅是 a、b 和 c

【问题讨论】:

  • 如果df2 中的值是100 而这个值不在df1['Item_ID'] 中会发生什么?有可能吗?

标签: python pandas


【解决方案1】:

您可以使用numpy 提高字典映射的速度。如果您的项目编号为0-N,这是微不足道的,如果不是,它会变得有点棘手,但仍然很容易做到。


如果df1 中的项目编号为0-N,则使用基本索引:

a = df1['Item_Name'].values
b = df2.values

pd.DataFrame(a[b], columns=df2.columns)

  Item_slot_1 Item_slot_2 Item_Slot_3
0           C           C           B
1           B           C           A
2           A           B           B

如果它们没有编号为0-N,这里有一个更通用的方法:

x = df1['Item_ID'].values
y = df1['Item_Name'].values
z = df2.values

m = np.arange(x.max() + 1, dtype=object)
m[x] = y

pd.DataFrame(m[z], columns=df2.columns)

  Item_slot_1 Item_slot_2 Item_Slot_3
0           C           C           B
1           B           C           A
2           A           B           B

只替换df2 的列的子集 也很简单,让我们演示只替换df2 的前两列:

x = df1['Item_ID'].values
y = df1['Item_Name'].values
cols = ['Item_slot_1', 'Item_slot_2']
z = df2[cols].values

m = np.arange(x.max() + 1, dtype=object)
m[x] = y

df2[cols] = m[z]

  Item_slot_1 Item_slot_2  Item_Slot_3
0           C           C            1
1           B           C            0
2           A           B            1

applyreplace 相比,这种类型的索引获得了巨大的性能提升:

import string

df1 = pd.DataFrame({'Item_ID': np.arange(26), 'Item_Name': list(string.ascii_uppercase)})
df2 = pd.DataFrame(np.random.randint(1, 26, (10000, 100)))

%%timeit
s = dict(zip(df1['Item_ID'], df1['Item_Name']))
df2.applymap(s.get)

158 ms ± 10.6 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%%timeit
s = dict(zip(df1['Item_ID'], df1['Item_Name']))
df2.replace(s)

750 ms ± 34.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

%%timeit
s = dict(zip(df1['Item_ID'], df1['Item_Name']))
df2.apply(lambda x: x.map(s))

93.1 ms ± 4.19 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%%timeit
x = df1['Item_ID'].values
y = df1['Item_Name'].values
z = df2.values
m = np.arange(x.max() + 1, dtype=object)
m[x] = y
pd.DataFrame(m[z], columns=df2.columns)

30.4 ms ± 182 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

【讨论】:

    【解决方案2】:

    通过zip 创建字典并将其传递给applymap,或replaceapplymap

    s = dict(zip(df1['Item_ID'], df1['Item_Name']))
    #if value not exist in df1['Item_ID'] get None in df2
    df2 = df2.applymap(s.get)
    

    或者:

    #if value not exist in df1['Item_ID'] get original value in df2
    df2 = df2.replace(s)
    

    或者:

    #if value not exist in df1['Item_ID'] get NaN in df2
    df2 = df2.apply(lambda x: x.map(s))
    

    print (df2)
      Item_slot_1 Item_slot_2 Item_Slot_3
    0           C           C           B
    1           B           C           A
    2           A           B           B
    

    编辑:

    您可以按进程名称指定列:

    cols = ['Item_slot_1','Item_slot_2','Item_Slot_3']
    
    df2[cols] = df2[cols].applymap(s.get)
    df2[cols] = df2[cols].replace(s)
    df2[cols] = df2[cols].apply(lambda x: x.map(s))
    

    【讨论】:

    • 我试过了,但是这是用 item_name 替换我的 df2 中的所有数字。 df2 中还有其他列,我没有在上面的示例中显示它们具有数值并且与 item-id/item_name 无关。有没有办法将映射函数指定到特定列?我试过这个 df2.apply(lambda x:x['item_slot_1'].map(s))。然而,这给了我 KeyError: ('item_1', 'occured at index match_id')
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-30
    • 2020-07-31
    • 2022-01-23
    • 1970-01-01
    相关资源
    最近更新 更多