如何在python中使用相似文本对数据帧进行分组
我有一个数据帧DF,如下所示:如何在python中使用相似文本对数据帧进行分组,python,pandas,pandas-groupby,Python,Pandas,Pandas Groupby,我有一个数据帧DF,如下所示: DF = pd.DataFrame({'Code':['abc', 'abc', 'abc', 'abc', 'def'], 'Description':['ABC String', 'ABC String', 'ABC String and sth', 'Only sth else', 'ABC String'], 'Value':[10, 20, 30, 40, 100]}) 我
DF = pd.DataFrame({'Code':['abc', 'abc', 'abc', 'abc', 'def'],
'Description':['ABC String', 'ABC String', 'ABC String and sth', 'Only sth else', 'ABC String'],
'Value':[10, 20, 30, 40, 100]})
我需要按代码和描述对其进行分组。按代码分组很简单:
GR = DF.groupby('Code')
现在我想继续按描述分组,以便将所有相等或相似的值(具有公共部分)分组在一起。你能帮我一个公式来得到这样的东西吗:
DF = pd.DataFrame({'Code':['abc', 'abc', 'abc', 'abc', 'def'],
'Description':['ABC String', 'ABC String', 'ABC String and sth', 'Only sth else', 'ABC String'],
'Value':[10, 20, 30, 40, 100]})
可能有两个问题:“相等值”和“相似值”。如果至少有关于“相等值”的任何提示,那就太好了。这实际上取决于您如何定义相似性。。。。如果您说出前10个字符,则可以使用字符串切片
DF = pd.DataFrame({'Code':['abc', 'abc', 'abc', 'abc', 'def'],
'Description':['ABC String', 'ABC String', 'ABC String and sth', 'Only sth else', 'ABC String'],
'Value':[10, 20, 30, 40, 100]})
DF.groupby(["Code", DF.Description.str[:10]])["Value"].sum()
这真的取决于你如何定义相似的。。。。如果您说出前10个字符,则可以使用字符串切片
DF = pd.DataFrame({'Code':['abc', 'abc', 'abc', 'abc', 'def'],
'Description':['ABC String', 'ABC String', 'ABC String and sth', 'Only sth else', 'ABC String'],
'Value':[10, 20, 30, 40, 100]})
DF.groupby(["Code", DF.Description.str[:10]])["Value"].sum()
要检查类似字符串,可以使用jellyish.levenshtein_distance。 其思想是迭代每个组并从组中获取最频繁的元素,然后计算相对于该最频繁元素的levenshtein_距离。如果距离接近0,则表示给定字符串相似,反之亦然
# from difflib import SequenceMatcher
from statistics import mode
import jellyfish
import pandas as pd
df = pd.DataFrame({'Code': ['abc', 'abc', 'abc', 'abc', 'def'],
'Description': ['ABC String', 'abc string', 'ABC String and sth', 'Only sth else', 'ABC String'],
'Value': [10, 20, 30, 40, 100]})
df_list = []
for grp,df in df.groupby('Code'):
df['distance'] = df['Description'].apply(lambda x : jellyfish.levenshtein_distance(x, mode(df['Description'])))
df['Description'] = mode(df['Description'])
df_list.append(df[df['distance'] < 10])
df = pd.concat(df_list).drop('distance', axis=1)
print(df)
为了更好、更准确地分析,请将字符串转换为小写,删除空格和标点符号,然后按照算法进行操作。要检查类似字符串,可以使用jellyish.levenshtein\u distance。 其思想是迭代每个组并从组中获取最频繁的元素,然后计算相对于该最频繁元素的levenshtein_距离。如果距离接近0,则表示给定字符串相似,反之亦然
# from difflib import SequenceMatcher
from statistics import mode
import jellyfish
import pandas as pd
df = pd.DataFrame({'Code': ['abc', 'abc', 'abc', 'abc', 'def'],
'Description': ['ABC String', 'abc string', 'ABC String and sth', 'Only sth else', 'ABC String'],
'Value': [10, 20, 30, 40, 100]})
df_list = []
for grp,df in df.groupby('Code'):
df['distance'] = df['Description'].apply(lambda x : jellyfish.levenshtein_distance(x, mode(df['Description'])))
df['Description'] = mode(df['Description'])
df_list.append(df[df['distance'] < 10])
df = pd.concat(df_list).drop('distance', axis=1)
print(df)
为了更好、更准确的分析,请将字符串转换为小写,删除空格和标点符号,然后按照算法进行操作。您也可以使用
fuzzyfuzzy
来计算LevenSien距离,即使存在两个以上的“相似”值
比如说
import numpy as np
import pandas as pd
from fuzzywuzzy import fuzz
DF = pd.DataFrame({'Code':['abc', 'abc', 'abc', 'abc', 'def', 'def', 'def', 'abc'],
'Description':['ABC String', 'ABC String',
'ABC String and sth', 'Only sth else',
'ABC String', 'CDEFGH', 'CDEFGH and sth',
'CDEFGH and sth',],
'Value':[10, 20, 30, 40, 50, 60, 70, 80]})
# for each unique value in Description
for d in DF.Description.unique():
# compute Levensthein distance
# and set to True if >= a limit
# (you may have to play around with it)
DF[d] = DF['Description'].apply(
lambda x : fuzz.ratio(x, d) >= 60
)
# set a name for the group
# here, simply the shortest
m = np.min(DF[DF[d]==True].Description)
# assign the group
DF.loc[DF.Description==d, 'group'] = m
print(DF)
Code Description Value ABC String group \
0 abc ABC String 10 True ABC String
1 abc ABC String 20 True ABC String
2 abc ABC String and sth 30 True ABC String
3 abc Only sth else 40 False Only sth else
4 def ABC String 50 True ABC String
5 def CDEFGH 60 False CDEFGH
6 def CDEFGH and sth 70 False CDEFGH
7 abc CDEFGH and sth 80 False CDEFGH
ABC String and sth Only sth else CDEFGH CDEFGH and sth
0 True False False False
1 True False False False
2 True False False False
3 False True False False
4 True False False False
5 False False True True
6 False False True True
7 False False True True
现在您可以groupby
创建的组
DF.groupby('group').Value.mean()
group
ABC String 27.5
CDEFGH 70.0
Only sth else 40.0
Name: Value, dtype: float64
您还可以使用
fuzzyfuzzy
来计算LevensInside距离,即使存在两个以上的“相似”值
比如说
import numpy as np
import pandas as pd
from fuzzywuzzy import fuzz
DF = pd.DataFrame({'Code':['abc', 'abc', 'abc', 'abc', 'def', 'def', 'def', 'abc'],
'Description':['ABC String', 'ABC String',
'ABC String and sth', 'Only sth else',
'ABC String', 'CDEFGH', 'CDEFGH and sth',
'CDEFGH and sth',],
'Value':[10, 20, 30, 40, 50, 60, 70, 80]})
# for each unique value in Description
for d in DF.Description.unique():
# compute Levensthein distance
# and set to True if >= a limit
# (you may have to play around with it)
DF[d] = DF['Description'].apply(
lambda x : fuzz.ratio(x, d) >= 60
)
# set a name for the group
# here, simply the shortest
m = np.min(DF[DF[d]==True].Description)
# assign the group
DF.loc[DF.Description==d, 'group'] = m
print(DF)
Code Description Value ABC String group \
0 abc ABC String 10 True ABC String
1 abc ABC String 20 True ABC String
2 abc ABC String and sth 30 True ABC String
3 abc Only sth else 40 False Only sth else
4 def ABC String 50 True ABC String
5 def CDEFGH 60 False CDEFGH
6 def CDEFGH and sth 70 False CDEFGH
7 abc CDEFGH and sth 80 False CDEFGH
ABC String and sth Only sth else CDEFGH CDEFGH and sth
0 True False False False
1 True False False False
2 True False False False
3 False True False False
4 True False False False
5 False False True True
6 False False True True
7 False False True True
现在您可以groupby
创建的组
DF.groupby('group').Value.mean()
group
ABC String 27.5
CDEFGH 70.0
Only sth else 40.0
Name: Value, dtype: float64
尝试使用函数添加布尔列,然后应用:
val = 'ABC String'
df['boo'] = df['description'].apply(lambda x: 1 if x.find(val)>=0 else 0)
df
代码
描述
价值
喝倒采
abc
ABC字符串
10
1.
abc
ABC字符串
20
1.
abc
ABC字符串和某物
30
1.
abc
只有别的
40
0
def
ABC字符串
100
1.
尝试使用函数添加布尔列,然后应用:
val = 'ABC String'
df['boo'] = df['description'].apply(lambda x: 1 if x.find(val)>=0 else 0)
df
代码
描述
价值
喝倒采
abc
ABC字符串
10
1.
abc
ABC字符串
20
1.
abc
ABC字符串和某物
30
1.
abc
只有别的
40
0
def
ABC字符串
100
1.
对于“相等值”,您是否尝试过类似于透视表的数据透视表?是否有其他许多“相等”字符串?除了ABC字符串之外?谢谢Amri,我会看一看。是的,Serge,原始集合中还有其他字符串。对于“相等值”,您是否尝试过类似pivot table的数据透视表?是否有许多其他“相等”字符串?除了ABC字符串之外?谢谢Amri,我会看一看。是的,Serge,原版还有其他弦乐。非常感谢@Nk03。这是一个有趣的方法,我将进一步研究,以适应我的最终解决方案。非常感谢@Nk03。这是一个有趣的方法,我将进一步研究,以适应我的最终解决方案。