Pandas 替换列中距离度量值大于阈值的图元

Pandas 替换列中距离度量值大于阈值的图元,pandas,dataframe,for-loop,Pandas,Dataframe,For Loop,考虑一个数据帧: company | label comp1 fashion comp2 fashionitem comp3 fashionable comp4 auto comp5 autoindustry comp6 automobile comp6 food comp7 delivery 我想稍微清理一下标签,我使用了字符串距离: from diffli

考虑一个数据帧:

company  |  label 

  comp1       fashion
  comp2       fashionitem
  comp3       fashionable
  comp4       auto
  comp5       autoindustry
  comp6       automobile
  comp6       food
  comp7       delivery
我想稍微清理一下标签,我使用了字符串距离:

from difflib import SequenceMatcher

def distance(a, b):
    return SequenceMatcher(None, a, b).ratio()
问题是,如何编写一个函数,在
label
列的任意两个元素之间应用
distance
函数,并在最后用最短的字符串替换所有类似的元素(距离高于某个阈值)

结果应该是:

company  |  label 

  comp1       fashion
  comp2       fashion
  comp3       fashion
  comp4       auto
  comp5       auto
  comp6       auto
  comp6       food
  comp7       delivery
我正在考虑执行2 for循环,但我的数据集可能相当大,有没有一种有效的方法来实现这一点

编辑:在阅读下面的回复时,我意识到我犯了一个错误。条目的总数(公司数)很大,但唯一标签的总数很小,不到1000个。我想,你可以应用
df.label(unique)
并使用它

创意

这种方法的思想是从阈值(ed)比率矩阵建立邻接矩阵。从邻接矩阵建立一个图,并从中得到连接的组件(集群)。获得所需的输出可能很棘手,但可以通过0.49的(绝对)阈值来实现

设置

from difflib import SequenceMatcher

import networkx as nx
import numpy as np
import pandas as pd

df = pd.DataFrame(data=[['comp1', 'fashion'],
                        ['comp2', 'fashionitem'],
                        ['comp3', 'fashionable'],
                        ['comp4', 'auto'],
                        ['comp5', 'autoindustry'],
                        ['comp6', 'automobile'],
                        ['comp6', 'food'],
                        ['comp7', 'delivery']], columns=['company', 'label'])


def distance(a, b):
    return SequenceMatcher(None, a, b).ratio()
代码

# get unique labels
labels = df['label'].unique()

# compute ratios
result = np.array([[distance(li, lj) for lj in labels] for li in labels])

# set diagonal to zero
result[np.arange(8), np.arange(8)] = 0

# build adjacency matrix
adjacency_matrix = (result > 0.49).astype(int)

# create graph
dg = nx.from_numpy_array(adjacency_matrix, create_using=nx.Graph)

# create mapping dictionary from connected components
mapping = {}
for component in nx.connected_components(dg):
    group = labels[np.array(list(component))]
    value = min(group, key=len)
    mapping.update({label: value for label in group})

result = df.assign(label=df.label.map(mapping))

print(result)
输出

  company     label
0   comp1   fashion
1   comp2   fashion
2   comp3   fashion
3   comp4      auto
4   comp5      auto
5   comp6      auto
6   comp6      food
7   comp7  delivery

您的数据集有多大?@Erfan目前“仅”有大约500k个条目,但我认为总共可能有200-300万个条目。如果您愿意接受近似解,精确解至少需要50万次运算。类似的元素是否总是共享一个共同的前缀?@DanielMesejo,我希望有一个精确的函数,它也适用于少量不同的标签(<1000)。我在上面的问题中做了一个更正,因为我意识到不同标签的数量很小。在你上面的例子中,fashion、fashionitem形成一个集群,因此必须用其中最短的一个来替换它们?听起来很有趣,但我已经将其应用到我的实际数据帧中,并获得标签“TV”对于新专栏中的每个人。您使用了什么阈值?0.49,返回“vi”,0.60返回“tv”。我真的不明白为什么。试着看看组件的值是什么,根据你说的,似乎只有一个连接的组件。对于阈值为0.8,似乎效果很好。我会接受这个答案,谢谢。