Объединить более 50% совпавших двух списков строк списка строк в пандах - PullRequest
1 голос
/ 18 октября 2019

У меня есть два df:

df1 = pd.DataFrame({'name1': ['ID1', 'ID2','ID3','ID4','ID5','ID6','ID7'], 'col1': ["S3,S22,S44", "S133,S32,S334", "S13,S24,S45", "S1,S2,S4,S5", "S3,S4,S5", "S3,S2,S5", "S38,S42,S9"],'col2': ['ab', 'ac','ad','ae','af','an','ak'],})
df2 = pd.DataFrame({'name2': ['Ik3', 'Ik1','Ik2','Ik7','Ik5','Ik6','Ik5'], 'col1': ["S3, S44, S22,S54", "S133, S32,S334, S30", "S13, S24,S45", "S11, S21,S4, S5", "S3, S4,S5", "S3, S22,S5", "S3, S4,S9, S10, S13"],'col2': ['ab', 'ae','ac','ad','af','ab','ak']})

df1

name1 col1          col2
ID1   S3,S22,S44    ab
ID2   S133,S32,S334 ac
ID3   S13,S24,S45   ad
ID4   S1,S2,S4,S5   ae
ID5   S3,S4,S5      af
ID6   S3,S2,S5      an
ID7   S38,S42,S9    ak

df2

name2   col1              col2
Ik3     S3,S44,S22,S54    ab
Ik1     S133,S32,S334,S30 ae
Ik2     S13,S24,S45       ac
Ik7     S11,S21,S4,S5     ad
Ik5     S3,S4,S5          af
Ik6     S3,S22,S5         ab
Ik5     S3,S4,S9,S10,S13  ak

Хотел бы сравнить два df списков col2 и объединить, которые имеютболее 50% совпадений, а остальные оставлены пустыми:

Желаемый вывод:

name1   col1          col2 M_name2  M_col1            M_col2 percentage 
ID1     S3,S22,S44    ab   Ik3      S3,S44,S22,S54    ab     75
ID1     S3,S22,S44    ab   Ik6      S3, S22,S5        ab     75
ID2     S133,S32,S334 ac   Ik1      S133,S32,S334,S30 ae     50
ID3     S13,S24,S45   ad   Ik2      S13,S24,S45       ac     100
ID4     S1,S2,S4,S5   ae   Ik5      S3,S4,S5          af     50
ID5     S3,S4,S5      af   Ik5      S3,S4,S5          af     100
ID6     S3,S2,S5      an   Ik5      S3,S4,S5          af     75 
ID7     S38,S42,S9    ak   NaN      NaN               NaN    NaN

Я попытался с функцией isin:

df1[df1.col2.isin(df2.col2)]

, но не получил желаемый вывод,Любое предложение приветствуется.

Ответы [ 2 ]

2 голосов
/ 18 октября 2019

Ваше описание и выходные данные не совпадают. Тем не менее, вот код, который, как мы надеемся, поможет вам начать.

def get_ratios(df1, df2):
  for a,b in zip(df1.col2, df2.col2):
    clean = lambda s: list(map(str.strip, s.split(',')))
    vals1, vals2 = clean(a), clean(b)

    inter = set(vals1).intersection(vals2)
    ratio = len(inter)/max(len(vals1), len(vals2))

    yield ratio

s = pd.Series(get_ratios(df1, df2))

Затем merge

(df1.merge(df2.rename(columns={'col1': 'nma1'}), 
          on=['col3'])
    .assign(percentage=s)) #.where(s > 0.5)

  col1          col2_x col3 nma1               col2_y  percentage
0  ID1     S3, S22,S44   ab  Ik3     S3, S44, S22,S54    0.750000
1  ID2  S133, S32,S334   ac  Ik1  S133, S32,S334, S30    0.750000
2  ID3   S13, S2 4,S45   ad  Ik2         S13, S24,S45    0.666667
3  ID4    S1, S2,S4 S5   ae  Ik7      S11, S21,S4, S5    0.000000
4  ID5       S3, S4,S5   af  Ik5            S3, S4,S5    1.000000
5  ID6       S3, S2,S5   as  Ik6            S3, S2,S5    1.000000
6  ID7       S3, S4,S9   ak  Ik5  S3, S4,S9, S10, S13    0.600000
0 голосов
/ 18 октября 2019

Смотрите мой ответ ниже. Я создал функцию для получения совпадения в процентах и ​​поместил NaN для colma nma1, если процент ниже 50%. Спасибо.

def get_percentage(x, y):
    '''
       Convert columns from string to list
       Compute the percentage
       Return NaN if less than 50% match
    '''
    x=[i.strip() for i in x.split(',')]
    y=[i.strip() for i in y.split(',')]
    percent = int(round((100.0 * len(set(x) & set(y))) / len(set(y)),0))
    return np.NaN if percent < 50 else percent  

# Use merge using both index
df = pd.merge(df1, df2, left_index=True, right_index=True, suffixes=('', '_y')).rename(columns={"col1": "name1", "col1_y": "nma1"})
# Get the percentage using apply/lambda functions
df['percent'] = df.apply(lambda x: get_percentage(x.col2, x.col2_y), axis=1)
# Remove not needed columns
df.drop(columns=['col2_y', 'col3_y'], inplace=True)
# Check if percent column is NaN
df['nma1']=df.apply(lambda x: np.NaN if np.isnan(x.percent) else x.nma1, axis=1)
df

Результат:

  name1 col2         col3   nma1    percent
0   ID1 S3, S22,S44     ab  Ik3     75.0
1   ID2 S133, S32,S334  ac  Ik1     75.0
2   ID3 S13, S2 4,S45   ad  Ik2     67.0
3   ID4 S1, S2,S4 S5    ae  NaN     NaN
4   ID5 S3, S4,S5       af  Ik5     100.0
5   ID6 S3, S2,S5       as  Ik6     100.0
6   ID7 S3, S4,S9       ak  Ik5     60.0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...