Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/38.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在python中使用相似文本对数据帧进行分组_Python_Pandas_Pandas Groupby - Fatal编程技术网

如何在python中使用相似文本对数据帧进行分组

如何在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,如下所示:

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。这是一个有趣的方法,我将进一步研究,以适应我的最终解决方案。