сгруппировать по фрейму с условием сходства metri c между двумя строками - PullRequest
0 голосов
/ 02 марта 2020

Я хочу сгруппировать фрейм данных по столбцу 'code', но только когда значения в 'name' значительно отличаются.

d = {'code': ['ABC', 'ABC','DB','DB','CDP'], 'name': ['abcde','abc de', 'defs','wokj','lkj']}
df = pd.DataFrame(data=d)
print(df)

  code    name
0  ABC   abcde
1  ABC  abc de
2   DB    defs
3   DB    wokj
4  CDP     lkj

, поэтому будет что-то вроде

df2 = df.groupby(['code']).agg(name = ('name', (' + '.join))).reset_index()
print(df2)

 code            name
0  ABC  abcde + abc de
1  CDP             lkj
2   DB     defs + wokj

, но AB C не должен быть группой и оставаться в качестве отдельного значения строки на основе условия, подобного следующему:

from difflib import SequenceMatcher

def similar(a, b):
    return SequenceMatcher(None, a, b).ratio()

print(similar('abcde', 'abc de'))
print(similar('defs', 'wokj'))

0.9090909090909091
0.0

Конечный результат, который я хочу получить, будет

 code            name
0  ABC          abcde
1  ABC         abc de
1  CDP             lkj
2   DB     defs + wokj

Как я могу поставить условие в группе?

1 Ответ

0 голосов
/ 02 марта 2020

Это может быть не лучшим решением, но я надеюсь, что это работает для вас. Некоторые части могут быть сделаны более pythoni c.

import numpy as np
import pandas as pd
from difflib import SequenceMatcher

def similar(dfg):
    df = pd.DataFrame(columns=['code', 'name'])

    if len(dfg) > 1:
        dfg = dfg.assign(a=1).merge(dfg[['name']].assign(a=1), on='a')
        dfg = dfg[dfg['name_x'] != dfg['name_y']]
        dfg[['name_x', 'name_y']] = pd.DataFrame(np.sort(dfg[['name_x', 'name_y']], axis=1), index=dfg.index)
        dfg = dfg.drop_duplicates(subset=['name_x', 'name_y'])
        dfg['sim'] = dfg.apply(lambda x: SequenceMatcher(None, x.name_x, x.name_y).ratio(), axis=1)

        for index, row in dfg.iterrows():
            if row['sim'] > 0:
                # this block could be more pythonic 
                row['name'] = row['name_x']
                df = df.append(row, sort=False)
                row['name'] = row['name_y']
                df = df.append(row, sort=False)
            else:
                row['name'] = row.name_x + ' + ' + row.name_y
                df = df.append(row, sort=False)
    else:
        df = df.append(dfg, sort=False)

    return df[['code', 'name']]

d = {'code': ['ABC', 'ABC', 'ABC', 'DB','DB','CDP'], 'name': ['abcde','abc de', 'xyz', 'defs','wokj','lkj']}
df = pd.DataFrame(data=d)
print(df)

df2 = df.groupby(['code']).apply(similar)
print(df2)

Вход:

  code    name
0  ABC   abcde
1  ABC  abc de
2   DB    defs
3   DB    wokj
4  CDP     lkj

Выход:

       code         name
code                    
ABC  1  ABC       abc de
     1  ABC        abcde
CDP  4  CDP          lkj
DB   1   DB  defs + wokj

Вход:

 code    name
0  ABC   abcde
1  ABC  abc de
2  ABC     xyz
3   DB    defs
4   DB    wokj
5  CDP     lkj

Выход:

       code          name
code                     
ABC  1  ABC        abc de
     1  ABC         abcde
     2  ABC   abcde + xyz
     5  ABC  abc de + xyz
CDP  5  CDP           lkj
DB   1   DB   defs + wokj
...