Pandas 根据另一个数据框中的匹配列填充新的数据框列

Posted

技术标签:

【中文标题】Pandas 根据另一个数据框中的匹配列填充新的数据框列【英文标题】:Pandas populate new dataframe column based on matching columns in another dataframe 【发布时间】:2017-02-10 12:23:50 【问题描述】:

我有一个df,其中包含我的主要数据,其中有一百万个rows。我的主要数据也有30个columns。现在我想在我的df 中添加另一列,名为categorycategorydf2 中的 column,其中包含大约 700 个 rows 和另外两个 columns,它们将与 df 中的两个 columns 匹配。

我首先在df2df 中设置一个index,它将在帧之间匹配,但是df2 中的一些indexdf 中不存在。

df2 中的其余列称为AUTHOR_NAMECATEGORY

df 中的相关列称为AUTHOR_NAME

df 中的某些AUTHOR_NAMEdf2 中不存在,反之亦然。

我想要的指令是:当df中的index匹配df2中的indexdf中的title匹配df2中的title时,将category添加到@ 987654356@,否则在category中添加NaN。

示例数据:

df2
           AUTHOR_NAME              CATEGORY
Index       
Pub1        author1                 main
Pub2        author1                 main
Pub3        author1                 main
Pub1        author2                 sub
Pub3        author2                 sub
Pub2        author4                 sub


df
            AUTHOR_NAME     ...n amount of other columns        
Index       
Pub1        author1                 
Pub2        author1     
Pub1        author2 
Pub1        author3
Pub2        author4 

expected_result
            AUTHOR_NAME             CATEGORY   ...n amount of other columns
Index
Pub1        author1                 main
Pub2        author1                 main
Pub1        author2                 sub
Pub1        author3                 NaN
Pub2        author4                 sub

如果我使用df2.merge(df,left_index=True,right_index=True,how='left', on=['AUTHOR_NAME']),我的df 会比预期的大三倍。

所以我认为合并可能是解决此问题的错误方法。我真正想做的是使用df2 作为查找表,然后根据是否满足某些条件将type 值返回到df

def calculate_category(df2, d):
    category_row = df2[(df2["Index"] == d["Index"]) & (df2["AUTHOR_NAME"] == d["AUTHOR_NAME"])]
    return str(category_row['CATEGORY'].iat[0])

df.apply(lambda d: calculate_category(df2, d), axis=1)

但是,这会引发一个错误:

IndexError: ('index out of bounds', u'occurred at index 7614')

【问题讨论】:

我不确定onleft_index/right_index 是否一起工作。也许你需要on=['Index', 'AUTHOR_NAME'](或类似的东西)。而且我不确定df2.merge(df,...) 中留下了哪个数据框。也许你需要how="right"pd.merge(left=df, right=df2, ...) 【参考方案1】:

考虑以下数据框 dfdf2

df = pd.DataFrame(dict(
        AUTHOR_NAME=list('AAABBCCCCDEEFGG'),
        title=      list('zyxwvutsrqponml')
    ))

df2 = pd.DataFrame(dict(
        AUTHOR_NAME=list('AABCCEGG'),
        title      =list('zwvtrpml'),
        CATEGORY   =list('11223344')
    ))

选项 1merge

df.merge(df2, how='left')

选项 2join

cols = ['AUTHOR_NAME', 'title']
df.join(df2.set_index(cols), on=cols)

两个选项都产生

【讨论】:

只是一个简短的说明..这对我来说很好..但在某些情况下我最终有重复..仍然不确定这是什么原因..但无论如何,删除重复保留只有一个(保持=第一个或保持=最后一个)..在这里查看文档pandas.pydata.org/pandas-docs/stable/generated/…【参考方案2】:

方法 1:

您可以改用concat 并删除IndexAUTHOR_NAME 合并列中存在的重复值。之后,使用isin 来检查成员资格:

df_concat = pd.concat([df2, df]).reset_index().drop_duplicates(['Index', 'AUTHOR_NAME'])
df_concat.set_index('Index', inplace=True)
df_concat[df_concat.index.isin(df.index)]

注意:Index 列假定设置为DF's 的索引列。


方法 2:

正确设置索引列后使用join如图:

df2.set_index(['Index', 'AUTHOR_NAME'], inplace=True)
df.set_index(['Index', 'AUTHOR_NAME'], inplace=True)

df.join(df2).reset_index()

【讨论】:

好吧,它对我有用。您是否为DFs 使用了适当的名称,并且两个框架中的Index 列是否设置为索引?请仔细检查。让我用你设置的名称编辑帖子。 是的,两个框架中的Index 列都设置为索引,我为DFs 使用了适当的名称【参考方案3】:

虽然这里的其他答案为所提出的问题提供了非常好的和优雅的解决方案,但我找到了一个资源,它既能以极其优雅的方式回答这个问题,又能提供一组非常清晰明了的示例,说明如何完成数据帧的连接/合并,有效地教授 LEFT、RIGHT、INNER 和 OUTER 连接。

Join And Merge Pandas Dataframe

老实说,我觉得这个话题之后任何进一步的寻求者都会想检查他的例子......

【讨论】:

但我们通常更喜欢这里的答案,而不是链接到其他地方。我从您的帖子中真正得到的唯一信息是解决方案在于使用join 和/或merge【参考方案4】:

您可以尝试以下方法。它会将指定列上的两个数据集合并为键。

expected_result = pd.merge(df, df2, on = 'CATEGORY', how = 'left')

【讨论】:

正如 cmets 在您之前的答案中所指出的,请提供您的答案的更多上下文并正确格式化它们。否则,由于质量低下,它们将不得不被标记为删除。感谢您帮助我们保持 *** 答案的有用性和高质量!

以上是关于Pandas 根据另一个数据框中的匹配列填充新的数据框列的主要内容,如果未能解决你的问题,请参考以下文章

如何根据 pandas 数据框中的数据类型填充 NaN 值?

遍历 pandas 数据框中的行并匹配列表中的元组并创建一个新的 df 列

用列不匹配的另一个数据框中的数据填充数据框[关闭]

合并 Pandas 数据框中的 2 列,用前一个值填充 NaN [重复]

在 pandas 中,如何根据一列中的唯一值创建列,然后根据另一列中的值填充它?

在使用数字列表搜索列后返回数据框中的所有行 - Python/Pandas