基于列之间的部分字符串匹配加入数据帧

Join dataframes based on partial string-match between columns

我有一个数据框,我想比较它们是否存在于另一个 df 中。

after_h.sample(10, random_state=1)

             movie           year   ratings
108 Mechanic: Resurrection   2016     4.0
206 Warcraft                 2016     4.0
106 Max Steel                2016     3.5
107 Me Before You            2016     4.5

我想比较以上电影是否出现在另一个df中。

              FILM                   Votes
0   Avengers: Age of Ultron (2015)   4170
1   Cinderella (2015)                 950
2   Ant-Man (2015)                   3000 
3   Do You Believe? (2015)            350
4   Max Steel (2016)                  560 

我想要这样的东西作为我的最终输出:

    FILM              votes
0  Max Steel           560

给定输入数据帧 df1df2,您可以通过 pd.Series.isin 使用布尔索引。要对齐电影字符串的格式,您需要首先将电影和年份从 df1:

连接起来
s = df1['movie'] + ' (' + df1['year'].astype(str) + ')'

res = df2[df2['FILM'].isin(s)]

print(res)

               FILM  VOTES
4  Max Steel (2016)    560

有两种方法:

  1. 获取部分匹配的行索引:FILM.startswith(title)FILM.contains(title)。以下之一:

    df1[ df1.movie.apply( lambda title: df2.FILM.str.startswith(title) ).any(1) ]

    df1[ df1['movie'].apply(lambda title: df2['FILM'].str.contains(title)).any(1) ]

     movie      year      ratings
106  Max Steel  2016      3.5
  1. 或者,如果将复合字符串列 df2['FILM'] 转换为它的两个组成列 movie_title (year),则可以使用 merge() .

.

# see code at bottom to recreate your dataframes
df2[['movie','year']] = df2.FILM.str.extract('([^\(]*) \(([0-9]*)\)')
# reorder columns and drop 'FILM' now we have its subfields 'movie','year'
df2 = df2[['movie','year','Votes']]
df2['year'] = df2['year'].astype(int)

df2.merge(df1)
       movie  year  Votes  ratings
0  Max Steel  2016    560      3.5

(在这里和 Python 聊天室感谢@user3483203 的帮助)

重新创建数据帧的代码:

import pandas as pd
from pandas.compat import StringIO

dat1 = """movie           year   ratings
108  Mechanic: Resurrection   2016     4.0
206  Warcraft                 2016     4.0
106  Max Steel                2016     3.5
107  Me Before You            2016     4.5"""

dat2 = """FILM                   Votes
0   Avengers: Age of Ultron (2015)   4170
1   Cinderella (2015)                 950
2   Ant-Man (2015)                   3000
3   Do You Believe? (2015)            350
4   Max Steel (2016)                  560"""

df1 = pd.read_csv(StringIO(dat1), sep='\s{2,}', engine='python', index_col=0)
df2 = pd.read_csv(StringIO(dat2), sep='\s{2,}', engine='python')

smci 的选项 1 已经差不多了,以下对我有用:

df1['Votes'] = ''
df1['Votes']=df1['movie'].apply(lambda title: df2[df2['FILM'].str.startswith(title)]['Votes'].any(0))

解释:

在 df1 中创建投票列

将 lambda 应用于 df1 中的每个电影字符串

lambda 查找 df2,选择 df2 中 Film 以电影标题开头的所有行

Select df2 的结果子集的 Votes 列

取此列中的第一个值与 any(0)