【问题标题】:Pandas: replace column values based on match from another columnPandas:根据另一列的匹配替换列值
【发布时间】:2016-11-22 19:54:46
【问题描述】:

我在第一个数据框df1["ItemType"] 中有一个列,如下所示,

数据框1

ItemType1
redTomato
whitePotato
yellowPotato
greenCauliflower
yellowCauliflower
yelloSquash
redOnions
YellowOnions
WhiteOnions
yellowCabbage
GreenCabbage

我需要根据从另一个数据框创建的字典来替换它。

Dataframe2

ItemType2          newType
whitePotato        Potato
yellowPotato       Potato
redTomato          Tomato
yellowCabbage   
GreenCabbage    
yellowCauliflower   yellowCauliflower
greenCauliflower    greenCauliflower
YellowOnions        Onions
WhiteOnions         Onions
yelloSquash         Squash
redOnions           Onions

请注意,

  • dataframe2 中的一些ItemTypeItemType 相同 dataframe1
  • dataframe2 中的一些 ItemType 具有 null 值,例如 YellowCabbage。
  • 数据帧2 中的ItemType 相对于dataframe 中的ItemType 出现故障

如果对应的Dataframe2 ItemType 中的值与newType 匹配,我需要替换Dataframe1 ItemType 列中的值,并牢记要点中列出的上述例外情况。
如果没有匹配,则值需要保持原样[没有变化]。

到目前为止我得到的是。

import pandas as pd

#read second `csv-file`
df2 = pd.read_csv('mappings.csv',names = ["ItemType", "newType"])
#conver to dict
df2=df2.set_index('ItemType').T.to_dict('list')

下面给出的匹配替换不起作用。他们正在插入 NaN 值而不是实际值。这些基于对 SO 的讨论 here

df1.loc[df1['ItemType'].isin(df2['ItemType'])]=df2[['NewType']]

df1['ItemType']=df2['ItemType'].map(df2)

提前致谢

编辑
两个数据框中的两个列标题具有不同的名称。所以dataframe1上的列是ItemType1,第二个数据框中的第一列是ItemType2。第一次编辑时错过了。

【问题讨论】:

    标签: python python-2.7 pandas dataframe


    【解决方案1】:

    使用map

    你需要的所有逻辑:

    def update_type(t1, t2, dropna=False):
        return t1.map(t2).dropna() if dropna else t1.map(t2).fillna(t1)
    

    'ItemType2'成为Dataframe2的索引

    update_type(Dataframe1.ItemType1,
                Dataframe2.set_index('ItemType2').newType)
    
    0                Tomato
    1                Potato
    2                Potato
    3      greenCauliflower
    4     yellowCauliflower
    5                Squash
    6                Onions
    7                Onions
    8                Onions
    9         yellowCabbage
    10         GreenCabbage
    Name: ItemType1, dtype: object
    

    update_type(Dataframe1.ItemType1,
                Dataframe2.set_index('ItemType2').newType,
                dropna=True)
    
    0                Tomato
    1                Potato
    2                Potato
    3      greenCauliflower
    4     yellowCauliflower
    5                Squash
    6                Onions
    7                Onions
    8                Onions
    Name: ItemType1, dtype: object
    

    验证

    updated = update_type(Dataframe1.ItemType1, Dataframe2.set_index('ItemType2').newType)
    
    pd.concat([Dataframe1, updated], axis=1, keys=['old', 'new'])
    


    时间

    def root(Dataframe1, Dataframe2):
        return Dataframe1['ItemType1'].replace(Dataframe2.set_index('ItemType2')['newType'].dropna())
    
    def piRSquared(Dataframe1, Dataframe2):
        t1 = Dataframe1.ItemType1
        t2 = Dataframe2.set_index('ItemType2').newType
        return update_type(t1, t2)
    

    【讨论】:

    • 时间测量万岁... +1
    • 欢迎回复,仍在查看。该解决方案还需要在第二个数据框newType 列中省略/删除对应值为emptynullItemType1 项目。所以这里应该删除yellowCabbageGreenCabbage,这样它们就不会出现在决赛桌中。
    • @Anil_M 这很简单,我强行把它放回去了。用可选的 dropna 参数更新了帖子。
    • @piRSquared - 我得到了NameError: global name 'dropna' is not defined return t1.map(t2).dropna() if dropna else t1.map(t2).fillna(t1)
    • @Anil_M 你把dropna=False 放在函数定义的签名中了吗?
    【解决方案2】:

    您可以将df2 转换为以'ItemType2' 为索引的Series,然后在df1 上使用replace

    # Make df2 a Series indexed by 'ItemType'.
    df2 = df2.set_index('ItemType2')['newType'].dropna()
    
    # Replace values in df1.
    df1['ItemType1'] = df1['ItemType1'].replace(df2)
    

    或者在一行中,如果你不想改变df2

    df1['ItemType1'] = df1['ItemType1'].replace(df2.set_index('ItemType2')['newType'].dropna())
    

    【讨论】:

    • 这里有 2 层问题。首先,当我现在尝试在 1 列上运行它时,我得到一个 MemoryError,对此可以做些什么。第二个问题,我正在尝试在我现在正在做的工作中使用它,但我需要一些更复杂的东西。我想应用一列来匹配一个包含一堆列(大约 100 个)和行的巨大数据框。我将如何修改代码以实现这一目标?
    【解决方案3】:

    此方法要求您将列名设置为“类型”,然后您可以使用合并和 np.where 进行设置

    df3 = df1.merge(df2,how='inner',on='type')['type','newType']
    
    df3['newType'] = np.where(df['newType'].isnull(),df['type'],df['newType'])
    

    【讨论】:

    • 嗨 - 感谢您的快速重播。我对问题做了些微改动。两个数据框中的两个列标题具有不同的名称。所以dataframe1上的列是ItemType1,第二个dataframe的第一列是ItemType2。此外,上述解决方案给出的错误为KeyError: 'type'
    • 'type' 的错误和 ItemType1 和 ItemType2 的问题是一回事。具体来说,我试图加入“类型”,而实际上 df 没有列“类型”,而是他们有“项目类型 1”和“项目类型 2”。就我个人而言,我会将两个 df 中的列重命名为 ItemType 并继续。但提供的其他解决方案可能更适合您的特定需求。
    猜你喜欢
    • 2017-03-04
    • 2022-09-23
    • 1970-01-01
    • 2015-10-23
    • 1970-01-01
    • 2019-02-03
    • 2018-09-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多