【问题标题】:Using loc and map to change values in multiple columns使用 loc 和 map 更改多列中的值
【发布时间】:2019-08-23 12:35:05
【问题描述】:

我有两个 DataFrame,它们具有相同的列名,并且每一行都有唯一的 Import_ID。我想基于相同的 Import_ID 将 df1 到 df2 的 2 列中的缺失值导入。

我已经为一列执行此操作并且效果很好,但我想同时为两列执行此操作。 对于我写的一篇专栏文章:

df2.loc[(numpy.isnan(df2['DeliveryNoteNo']))& (~numpy.isnan(df1['DeliveryNoteNo'])), 'DeliveryNoteNo'] = df2['Import_ID'].map(df1.set_index('Import_ID')['DeliveryNoteNo'])

这很好用,所以我想对 2 列做同样的事情,这样每次我做更新时都会做 df2 它也会给出更新的日期。

我试过这个,但它只返回一个错误:“TypeError: 'DataFrame' object is not callable”

df2.loc[(numpy.isnan(df2.InvoiceNo))& (~numpy.isnan(df1['InvoiceNo'])), ['InvoiceNo','Modified_Date']] = df2['Import_ID'].map(df1.set_index('Import_ID')[['InvoiceNo', 'Modified_Date']])

例如: df1:

     InvoiceNo     OrderNo  DeliveryNoteNo     Modified_Date   Import_ID
0   950094591.0  7027514279    1.000000e+00  23-08-2019 14:30  7027514279_100
1   950094591.0  7027514279    2.000000e+00  23-08-2019 14:30  7027514279_100.1
2                7027514279                  23-08-2019 14:30  7027514279_100.2

df2:

     InvoiceNo     OrderNo  DeliveryNoteNo     Modified_Date   Import_ID
0                7027514279    1.000000e+00  21-08-2019 14:30  7027514279_100
1   950094591.0  7027514279                  21-08-2019 14:30  7027514279_100.1
2                7027514279                  21-08-2019 14:30  7027514279_100.2

df2 稍后应如下所示:

     InvoiceNo     OrderNo  DeliveryNoteNo     Modified_Date   Import_ID
0   950094591.0  7027514279    1.000000e+00  23-08-2019 14:30  7027514279_100
1   950094591.0  7027514279    2.000000e+00  23-08-2019 14:30  7027514279_100.1
2                7027514279                  21-08-2019 14:30  7027514279_100.2

【问题讨论】:

  • 你试过合并吗?
  • 是的,我尝试了合并,它只显示了 df1 行,并且没有一个与 df1 不同的 df2
  • 您的示例数据帧上没有importID,对吗?还是只是索引?如果是这种情况,请使用df2.combine_first(df1)
  • 我忘记将它添加到示例中,有 20 多个不同的列,由于我正在处理这 4 个列,所以我忘记添加它,..我现在更新了我的问题

标签: python pandas numpy csv


【解决方案1】:

试试这个

df2.set_index('Import_ID').combine_first(df1.set_index('Import_ID')).reset_index(drop=True)

输出:

        InvoiceNo     OrderNo  DeliveryNoteNo     Modified_Date
0     950094591.0  7027514279             1.0  21-08-2019 14:30
1     950094591.0  7027514279             2.0  21-08-2019 14:30
2             NaN  7027514279             NaN  21-08-2019 14:30

【讨论】:

  • 这意味着它总是会更新所有内容,即使 InvoiceNo 和 DeliveryNoteNo 列没有更新......我不能那样使用它,我需要它专门用于这三列.这意味着列 Modified_Date 只会在导入 InvoiceNo 或 DeliveryNoteNo 时采用新日期,否则它保持不变,即使在 df1 它获得了新的 Modified_date。希望我解释清楚
  • 这几乎是正确的。此操作的结果不会就地修改df2,因此您可以从此数据框中获取结果并仅获取您需要的列,同意吗?
【解决方案2】:

您是否尝试过将mapfillna 结合使用的非详尽映射?

基本上,您需要先根据df1 中的列值创建两个字典,以将要更新的值放在df2 的2 列中:

dictionary_1 = dict(zip(df1['Import_ID'], df1['DeliveryNoteNo']))
dictionary_2 = dict(zip(df1['Import_ID'], df1['InvoiceNo']))

然后,您使用这些字典更新df2,但如果返回False,则使用带有等于df2 列中原始值的参数的fillna

df2['DeliveryNoteNo'] = df2['Import_ID'].map(dictionary_1).fillna(df2['DeliveryNoteNo'])

对要更新的第二列执行相同操作:

df2['InvoiceNo'] = df2['Import_ID'].map(dictionary_1).fillna(df2['InvoiceNo'])

如果map 返回False,则fillna 参数不会为您的列提供Nan 值,这意味着它不会更新任何与键中ID 不同的现有值在你的两个字典里。

希望这会有所帮助:))。

【讨论】:

  • 这是我想避免的,我认为有一个类似于我当前代码的选项可以做到这一点。但感谢您的回答
猜你喜欢
  • 2019-12-16
  • 2020-10-23
  • 2020-12-04
  • 1970-01-01
  • 2019-09-04
  • 2019-12-02
  • 1970-01-01
  • 2021-08-31
  • 2022-12-09
相关资源
最近更新 更多