【问题标题】:Compare columns in two different data frames if match found copy email from df2 to df1如果找到匹配,则比较两个不同数据框中的列,将电子邮件从 df2 复制到 df1
【发布时间】:2017-10-15 20:52:25
【问题描述】:

我有两个列名不同的数据框,每个有 10 行。我要做的是比较列值,如果它们匹配,则将电子邮件地址从 df2 复制到 df1。我看过这个例子,但我的列名不同How to join (merge) data frames (inner, outer, left, right)?。我已经看到this example 以及np.where 使用了多个条件,但是当我这样做时,它给了我以下错误:

ValueError: Wrong number of items passed 2, placement implies 1

我想做的事:

我想要做的是将 df1 的第一行 2 列(first,last_huge)与 df2 列的所有行(first_small,last_small)进行比较,如果找到匹配项,则从 df2 中的特定列获取电子邮件地址并分配它到 df1 中的一个新列。任何人都可以帮我解决这个问题我只复制了下面的相关代码并且它不能完全工作只是向 new_email 添加 5 条新记录。

最初我所做的是将 df1['first'] 与 df2['first'] 进行比较

data1 = {"first":["alice", "bob", "carol"],
         "last_huge":["foo", "bar", "baz"],
         "street_huge": ["Jaifo Road", "Wetib Ridge", "Ucagi View"],
         "city_huge": ["Egviniw", "Manbaali", "Ismazdan"],
         "age_huge": ["23", "30", "36"],
         "state_huge": ["MA", "LA", "CA"],
         "zip_huge": ["89899", "78788", "58999"]}

df1 = pd.DataFrame(data1)

data2 = {"first_small":["alice", "bob", "carol"],
         "last_small":["foo", "bar", "baz"],
         "street_small": ["Jsdffo Road", "sdf Ridge", "sdfff View"],
         "city_huge": ["paris", "london", "rome"],
         "age_huge": ["28", "40", "56"],
         "state_huge": ["GA", "EA", "BA"],
         "zip_huge": ["89859", "78728", "56999"],
         "email_small":["alice@xyz.com", "bob@abc.com", "carol@jkl.com"],
         "dob": ["31051989", "31051980", "31051981"],
         "country": ["UK", "US", "IT"],
         "company": ["microsoft", "apple", "google"],
         "source": ["bing", "yahoo", "google"]}

df2 = pd.DataFrame(data2)

df1['new_email'] = np.where((df1[['first']] == df2[['first_small']]), df2[['email_small']], np.nan)

现在只向 new_email 添加 5 条记录,其余为 nan。并向我显示此错误:

ValueError: Can only compare identically-labeled Series objects

【问题讨论】:

  • 当您可以在线提供具有代表性的示例数据时,请不要发布数据截图。它使其他人更容易帮助您。
  • 好的,我会解决的

标签: python pandas numpy


【解决方案1】:

试试merge:

(df1.merge(df2[["first_small", "last_small", "email_small"]], 
           how="left", 
           left_on=["first", "last_huge"], 
           right_on=["first_small", "last_small"])
    .drop(['first_small','last_small'], 1))

例子:

data1 = {"first":["alice", "bob", "carol"], 
         "last_huge":["foo", "bar", "baz"]}
df1 = pd.DataFrame(data1)

data2 = {"first_small":["alice", "bob", "carol"], 
         "last_small":["foo", "bar", "baz"],
         "email_small":["alice@xyz.com", "bob@abc.com", "carol@jkl.com"]}
df2 = pd.DataFrame(data2)

(df1.merge(df2[["first_small", "last_small", "email_small"]], 
           how="left", 
           left_on=["first", "last_huge"], 
           right_on=["first_small", "last_small"])
    .drop(['first_small','last_small'], 1))

输出:

   first last_huge    email_small
0  alice       foo  alice@xyz.com
1    bob       bar    bob@abc.com
2  carol       baz  carol@jkl.com

【讨论】:

  • 不客气!如果此解决方案解决了您的问题,请通过单击答案旁边的复选标记将其标记为已接受。
  • 一个问题,如果df1的行中的块大小与df2不同,那不会有问题吧?
  • 只要每个名字对在df2 中只有一个电子邮件地址,那么df1df2 的长度是否不同就没有关系。 (我认为这就是您所说的块大小。)如果df1 中的某些行在df2 中没有匹配的电子邮件,则email_small 字段将显示为NaN
  • 有个小问题,实际文件中data1“first”的列名是“first_name”,data2“first_small”的列名也是“first_name”。 drop 语句实际上是从 data1 和 data2 中删除列,我如何防止它从 data1 中删除列并仅从 data2 中删除它??
  • 如果您想保留first_name,只需将first_name 包含在on=[] 列表中,然后将其从drop 列表中删除。该列不会重复。
【解决方案2】:

通过使用 andrew_reece 的示例数据 :-) pd.concat

pd.concat([df1.set_index(["first", "last_huge"]),df2.set_index(["first_small", "last_small"])['email_small']],axis=1).reset_index().dropna()
Out[23]: 
   first last_huge    email_small
0  alice       foo  alice@xyz.com
1    bob       bar    bob@abc.com
2  carol       baz  carol@jkl.com

通过使用您的数据

pd.concat([df1.set_index(["first", "last_huge"]),df2.set_index(["first_small", "last_small"])['email_small']],axis=1).reset_index()
Out[97]: 
   first last_huge age_huge city_huge state_huge  street_huge zip_huge  \
0  alice       foo       23   Egviniw         MA   Jaifo Road    89899   
1    bob       bar       30  Manbaali         LA  Wetib Ridge    78788   
2  carol       baz       36  Ismazdan         CA   Ucagi View    58999   
     email_small  
0  alice@xyz.com  
1    bob@abc.com  
2  carol@jkl.com  

使用map更新

df1['email_small']=(df1['first']+df1['last_huge']).map(df2.set_index(df2['first_small']+df2['last_small'])['email_small'])
df1
Out[115]: 
  age_huge city_huge  first last_huge state_huge  street_huge zip_huge  \
0       23   Egviniw  alice       foo         MA   Jaifo Road    89899   
1       30  Manbaali    bob       bar         LA  Wetib Ridge    78788   
2       36  Ismazdan  carol       baz         CA   Ucagi View    58999   
     email_small  
0  alice@xyz.com  
1    bob@abc.com  
2  carol@jkl.com  

【讨论】:

  • 将公共字段移动到索引然后concat 是一个巧妙的技巧。
  • @andrew_reece 这里唯一的限制是密钥不是唯一的。
  • 谢谢!但是 first 和 last_huge 列被重命名为 level_0 和 level_1 其他列都是 NaN 除了 level_0、level_1 和 email_small
  • @Wcan 你的数据和样本数据一样吗?
  • 我很抱歉,上面给出的示例数据不一样,但我改变了它。
猜你喜欢
  • 1970-01-01
  • 2019-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-20
  • 2021-04-16
相关资源
最近更新 更多