pandas :如果数据框中的值包含另一个数据框中的字符串,请追加列 [英] Pandas : if value in a dataframe contains string from another dataframe, append columns

查看:93
本文介绍了 pandas :如果数据框中的值包含另一个数据框中的字符串,请追加列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

比方说,我有两个数据帧df1和df2. 如果df1的特定列的值包含df2的特定列中的字符串,我想将df2的某些列附加到df1,否则不包含NaN.

Let's say I have two dataframes df1 and df2. I want to append some columns of df2 to df1 if the value of a specific column of df1 contains the string in a specific column of df2, NaN if not.

一个小例子:

import pandas as pd
df1 = pd.DataFrame({'col': ['abc', 'def', 'abg', 'xyz']})
df2 = pd.DataFrame({'col1': ['ab', 'ef'], 'col2': ['match1', 'match2'], 'col3': [1, 2]})

df1:
   col
0  abc
1  def
2  abg
3  xyz

df2:

  col1    col2    col3
0   ab  match1       1
1   ef  match2       2

我想要:

   col   col2_match   col3_match
0  abc       match1            1
1  def       match2            2
2  abg       match1            1
3  xyz          NaN          NaN

我设法以一种肮脏和低效的方式来做到这一点,但就我而言,df1包含大约10万行,并且要花很多时间……

I managed to do it in a dirty and unefficient way, but in my case df1 contains like 100K rows and it takes forever...

提前谢谢!

编辑

有点脏,但是可以相对快速地完成工作(尽管如此,我仍然认为这是最聪明的方式...):

A bit dirty but gets the work done relatively quickly (I still thinks there exists a smartest way though...):

import pandas as pd
import numpy as np


df1 = pd.DataFrame({'col': ['abc', 'def', 'abg']})
df2 = pd.DataFrame({'col1': ['ab', 'ef'],
                    'col2': ['match1', 'match2'],
                    'col3': [1, 2]})


def return_nan(tup):
    return(np.nan if len(tup[0]) == 0 else tup[0][0])


def get_indexes_match(l1, l2):
    return([return_nan(np.where([x in e for x in l2])) for e in l1])


def merge(df1, df2, left_on, right_on):
    df1.loc[:, 'idx'] = get_indexes_match(df1[left_on].values,
                                          df2[right_on].values)
    df2.loc[:, 'idx'] = np.arange(len(df2))
    return(pd.merge(df1, df2, how='left', on='idx'))


merge(df1, df2, left_on='col', right_on='col1')

推荐答案

您可以像这样使用python difflib模块进行模糊匹配

You can use python difflib module for fuzzy match like this

import difflib 
difflib.get_close_matches
df1.col = df1.col.map(lambda x: difflib.get_close_matches(x, df2.col1)[0])

所以现在您的df1是

    col
0   ab
1   ef
2   ab

如果希望保持df1不变,可以将其称为df3.

You can call it df3 if you wish to keep df1 unaltered.

现在您可以合并

merged = df1.merge(df2, left_on = 'col', right_on = 'col1', how = 'outer').drop('col1', axis = 1)

合并的数据框看起来像

    col col2    col3
0   ab  match1  1
1   ab  match1  1
2   ef  match2  2

如果像给出的新示例那样没有匹配项,则只需在lambda中放置一个条件

In case of no match like the new example given, you just need to put a conditional in lambda

df1.col = df1.col.map(lambda x: difflib.get_close_matches(x, df2.col1)[0] if difflib.get_close_matches(x, df2.col1) else x)

现在合并后您会得到

    col col2    col3
0   ab  match1  1
1   ab  match1  1
2   ef  match2  2
3   xyz NaN     NaN

这篇关于 pandas :如果数据框中的值包含另一个数据框中的字符串,请追加列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆