【问题标题】:Pandas: Replace values in column based on a match in a different columnPandas:根据不同列中的匹配替换列中的值
【发布时间】:2022-09-23 00:30:26
【问题描述】:

我正在重新设置问题,以使每个人都更清楚我遇到问题的 DataFrame。 DataFrame 包含超过 100,000 行,超过 10 列。我遇到的重要问题是填写 id 列中之前与 type 列中的某个值匹配的任何值。 id 列中的值不是唯一的。有时idtype 的值都是 NIL。

注意:不应影响事物的顺序,因为记录与其他列一起注明日期。也没有空单元格,所有空单元格都用“NIL”填充。

目标:仅在id 列中替换尽可能多的“NIL”。我不关心type 列中的任何“NIL”值。但其他一切都必须保持不变。

我假设这可以在没有循环的情况下完成。谢谢您的帮助!真的很感激,陌生人!

当前数据框

COL1 id type COL4 COL5
NIL 123 moving NIL NIL
... 123 lend ... ...
NIL 456 penny ... NIL
... NIL appendix NIL ...
... 251 appendix ... ...
NIL NIL lend ... NIL
... 665 NIL NIL ...
... NIL NIL ... ...
... 251 retailer NIL NIL
NIL 251 appendix ... NIL
NIL 456 NIL ... NIL

预期的数据框

COL1 id type COL4 COL5
NIL 123 moving NIL NIL
... 123 lend ... ...
NIL 456 penny ... NIL
... 251 appendix NIL ...
... 251 appendix ... ...
NIL 123 lend ... NIL
... 665 NIL NIL ...
... NIL NIL ... ...
... 251 retailer NIL NIL
NIL 251 appendix ... NIL
NIL 456 NIL ... NIL

    标签: python pandas dataframe numpy replace


    【解决方案1】:

    您可以使用合并

    # assemble the dataframe
    In [4]: a
    Out[4]: 
    [26235,
     'fruit',
     26235,
     'veggie',
     32256,
     'NIL',
     'NIL',
     'pawn',
     12415,
     'NIL',
     'NIL',
     'fruit',
     'NIL',
     'veggie',
     24145,
     'pawn',
     'NIL',
     'NIL']
    
    In [5]: df = pandas.DataFrame({'id':a[::2], 'type':a[1::2]})
     
    #      id    type
    #0  26235   fruit
    #1  26235  veggie
    #2  32256     NIL
    #3    NIL    pawn
    #4  12415     NIL
    #5    NIL   fruit
    #6    NIL  veggie
    #7  24145    pawn
    #8    NIL     NIL
    
    
    In [6]: id_is_nill = df.id=="NIL"
    
    In [7]: left = df.loc[id_is_nill].reset_index()
    
    In [8]: right = df.loc[~id_is_nill].reset_index()
    
    In [9]: mrg = pandas.merge(left, right, on='type').query("type != 'NIL'")
    
    In [10]: mrg
    Out[10]: 
       index_x id_x    type  index_y   id_y
    0        3  NIL    pawn        7  24145
    1        5  NIL   fruit        0  26235
    2        6  NIL  veggie        1  26235
    
    In [11]: df.loc[mrg.index_x, 'id'] = mrg.id_y.values
    
    In [12]: df
    Out[12]: 
          id    type
    0  26235   fruit
    1  26235  veggie
    2  32256     NIL
    3  24145    pawn
    4  12415     NIL
    5  26235   fruit
    6  26235  veggie
    7  24145    pawn
    8    NIL     NIL
    

    基于字典查询的替代方法

    # starting with original dataframe
    In [5]: df = pandas.DataFrame({'id':a[::2], 'type':a[1::2]})
     
    #      id    type
    #0  26235   fruit
    #1  26235  veggie
    #2  32256     NIL
    #3    NIL    pawn
    #4  12415     NIL
    #5    NIL   fruit
    #6    NIL  veggie
    #7  24145    pawn
    #8    NIL     NIL
    
    In [60]: id_lookup = df.query("id!= 'NIL' and type != 'NIL'").set_index('type').to_dict()['id']
    
    In [61]: id_lookup
    Out[61]: {'fruit': 26235, 'veggie': 26235, 'pawn': 24145}
    
    In [62]: 
    
    In [67]: df['patched_id'] = [id_lookup[t] if t in id_lookup else i for i,t in zip(df.id, df.type)]
    
    In [68]: df
    Out[68]: 
          id    type patched_id
    0  26235   fruit      26235
    1  26235  veggie      26235
    2  32256     NIL      32256
    3    NIL    pawn      24145
    4  12415     NIL      12415
    5    NIL   fruit      26235
    6    NIL  veggie      26235
    7  24145    pawn      24145
    8    NIL     NIL        NIL
    
    

    【讨论】:

    • 答案有效,但似乎不适用于大型数据集。你会推荐循环吗?
    • 取决于慢步到底在哪里......
    • 我添加了另一种可能更好地扩展的方法。另一种选择是使用我发布的原始方法,但对仅包含相关列(类型和 id)的数据框执行合并,然后使用 dataframe update method 将结果(新的 id 列)与原始的更大数据框合并
    【解决方案2】:

    这是一种方法

    创建类型和id的字典,然后使用loc填充缺失值

    d=df[df['id'].ne('NIL')].drop_duplicates(subset=['type']).to_dict()
    
    df.loc[df['id'].eq('NIL'), 'id'] = df['type'].map(d)
    df
    
    id  type
    0   26235   fruit
    1   26235   veggie
    2   32256   NIL
    3   24145   pawn
    4   12415   NIL
    5   26235   fruit
    6   26235   veggie
    7   24145   pawn
    

    【讨论】:

    • 不能用,怎么回事?请注意,数据框中还有多个其他列。
    • 字典创建成功了吗?检查打印(d)。类型中可能有空格,因此在使用 df['type'].str.strip().map(d) 进行映射之前将其剥离
    • 不成功,NIL 似乎已被 NaN 取代。有任何想法吗?请注意,ID 不是唯一的,它们是重复的。
    【解决方案3】:

    你可以做:

    #d = df.loc[(df.id != 'NIL') & (df.type != 'NIL')].set_index('type')['id']
    d = df[df!='NIL'].dropna().set_index('type')['id']
    
    df.loc[df.id =='NIL', 'id'] = df.loc[df.id == 'NIL', 'type'].map(d)
    

    打印(df):

         id    type
    0  26235   fruit
    1  26235  veggie
    2  32256     NIL
    3  24145    pawn
    4  12415     NIL
    5  26235   fruit
    6  26235  veggie
    7  24145    pawn
    

    【讨论】:

    • “InvalidIndexError:重新索引仅对具有唯一值的索引对象有效”注意:DF 中还有其他列,但不确定这是否重要。
    • @ngnwoenqwl 您可能在其他列中也有“NIL”。尝试更新的答案。
    • 没有成功,NIL 似乎被替换为 NaN
    猜你喜欢
    • 2016-11-22
    • 1970-01-01
    • 2015-06-30
    • 1970-01-01
    • 2018-09-08
    • 2017-03-04
    • 2021-07-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多