基于另一个数据框中的匹配列填充新的数据框列

45

我有一个包含一百万行数据和30列数据的df。现在我想要在df中添加另一列名为category的数据。这个categorydf2中的一列,其中包含大约700个rows和另外两个columns,这两个columnsdf中的两个columns匹配。

我开始先在df2df中设置一个匹配的index,但是df2中的一些index并不存在于df中。

df2中的其余列称为AUTHOR_NAMECATEGORY

df中相关的一列被称为AUTHOR_NAME

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

我需要的指令是:当df中的indexdf2中的index匹配,并且titledf中与titledf2中匹配时,将category添加到df中;否则,在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, ...) - furas
4个回答

47

考虑以下数据框 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')
    ))

选项 1
合并

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

选项 2
加入

cols = ['AUTHOR_NAME', 'title']
df.join(df2.set_index(cols), on=cols)
两个选项都会产生同样的结果。

在此输入图片描述


只是一个快速的提示..对我来说很好用..但在某些情况下,我最终会有重复项..仍然不确定原因是什么..但无论如何,删除重复项只保留一个(keep = first OR keep = last)..在这里查看文档 https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.drop_duplicates.html - Abdelrahman Shoman

2

方法一:

您可以使用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)]

Image

注意:假设列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()

Image


嗯,虽然对我有效,但你是否使用了适当的DFs名称?并且你的两个数据框中的Index列是否都设置为索引?请再仔细检查一下。让我编辑帖子,使用你设置的名称。 - Nickil Maveli
是的,两个数据框中的Index列都被设置为索引,并且我使用了适当的名称来表示数据框。 - user3471881

1
您可以尝试以下方法。它将使用指定列作为键将两个数据集合并在一起。
expected_result = pd.merge(df, df2, on = 'CATEGORY', how = 'left')

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

-1

尽管其他回答在这里提供了非常好和优雅的解决方案,但我发现一个资源,它以极其优雅的方式回答了这个问题,并给出了一组清晰明了的示例,展示如何有效地实现数据框的连接/合并,有效地教授了LEFT、RIGHT、INNER和OUTER连接。

Join And Merge Pandas Dataframe

我真诚地认为,任何进一步寻求这个主题的人也会想要查看他的示例...


2
但我们通常更喜欢答案在这里发布,而不是链接到其他地方。从您的帖子中我真正得到的是解决方案在使用 join 和/或 merge 中。 - Teepeemm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接