Получить среднее значение столбца только тех строк с нечетким соотношением выше заданного значения - PullRequest
1 голос
/ 18 июня 2020

Я пытаюсь получить для каждого значения в сгруппированном pandas столбце среднее значение другого столбца с 1 и 0 только тех строк, где fuzz.partial_ratio() столбца превышает заданный предел (скажем, выше 80).

Я знаю, что это может быть непонятно, поэтому вот пример моих данных

col1 col2      col3
A    Miami       1
A    Miami       0
A    Miami.      0
A    Barcelona   0
A    Barc elona  0
A    Shanghai    1
A    Shangai     0
B    Miami       1
B    Miami       1
B    Miami.      1
B    Barcelona   0
B    Barc elona  0
B    Shanghai    1
B    Shangai    0

Я пытаюсь groupby('col1') и для каждого значения в col2 оцените в новом столбце среднее значение col3 только тех строк, где fuzzy_ratio из col2 больше 80.

Например, в строке 0, df['col2']='Miami' . Затем я хочу получить fuzzy_ratio() из «Майами» со всеми значениями в col2 с df['col1']='A' и получить среднее значение col3 тех строк, где соотношение> 80, и сохранить его в новом столбец. Это будут строки 1 и 2, что равно 0. То же самое для строки 2, но в этом случае среднее значение будет 0,5.

Результат, который я пытаюсь получить, будет выглядеть как это:

col1 col2      col3 col4
A    Miami       1   0.33
A    Miami       0   0.33
A    Miami.      0   0.33
A    Barcelona   0   0
A    Barc elona  0   0
A    Shanghai    1   0.5
A    Shangai     0   0.5
B    Miami       1   1
B    Miami       1   1
B    Miami.      1   1
B    Barcelona   0   0
B    Barc elona  0   0
B    Shanghai    1   0.5
B    Shangai     0   0.5

Мне удалось сделать это с помощью for l oop для каждого значения в col2, но у меня есть относительно большой набор данных (+10 миллионов строк), и это займет навсегда.

Есть ли способ избежать этого for l oop для выполнения этой задачи?

Большое спасибо !!!!!

1 Ответ

1 голос
/ 19 июня 2020

Это неэффективно, но я думаю, что подойдет вам.

from fuzzywuzzy import fuzz
import pandas as pd
import numpy as np

# helper function
def remove_element(lst, index):
    "Removes an element from a list based on the index"
    tmp = lst.copy()
    del tmp[index]
    return tmp


df = pd.DataFrame({'col1':['A', 'A', 'A', 'A', 'A', 'A', 'A', 
                           'B', 'B', 'B', 'B', 'B', 'B', 'B'], 
                  'col2':['Miami', 'Miami', 'Miami.', 'Barcelona', 'Barc elona', 
                         'Shanghai', 'Shangai', 'Miami', 'Miami', 'Miami.', 
                         'Barcelona', 'Barc elona', 'Shanghai', 'Shangai'], 
                  'col3':[1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0]})

# create a column that indicates the index of the element within the group
df['col2_index'] = 1
df['col2_index'] = df.groupby('col1')['col2_index'].cumsum() - 1

# create a list of the elements within the group
df['col2_list'] = df['col1'].map(df.groupby('col1')['col2'].apply(list))
df['col3_list'] = df['col1'].map(df.groupby('col1')['col3'].apply(list))

# remove the element associated with col2 and col3 respectively
df['col2_list'] = df.apply(lambda x: remove_element(x['col2_list'], x['col2_index']), axis=1)
df['col3_list'] = df.apply(lambda x: remove_element(x['col3_list'], x['col2_index']), axis=1)

# apply the threshold of 80 for the partial_ratio
df['key'] = df.apply(lambda x: 
         np.array([fuzz.partial_ratio(x['col2'], el) for el in x['col2_list']]) >= 80, axis=1)

# get the average of col3 for those that pass the threshold
df['result'] = df.apply(lambda x: np.mean(np.array(x['col3_list'])[x['key']]), axis=1)

df

 col1   col2       col3 col2_index  col2_list                                           col3_list           key                                      result
0   A   Miami       1   0           [Miami, Miami., Barcelona, Barc elona, Shangha...   [0, 0, 0, 0, 1, 0]  [True, True, False, False, False, False]    0.0
1   A   Miami       0   1           [Miami, Miami., Barcelona, Barc elona, Shangha...   [1, 0, 0, 0, 1, 0]  [True, True, False, False, False, False]    0.5
2   A   Miami.      0   2           [Miami, Miami, Barcelona, Barc elona, Shanghai...   [1, 0, 0, 0, 1, 0]  [True, True, False, False, False, False]    0.5
3   A   Barcelona   0   3           [Miami, Miami, Miami., Barc elona, Shanghai, S...   [1, 0, 0, 0, 1, 0]  [False, False, False, True, False, False]   0.0
4   A   Barc elona  0   4           [Miami, Miami, Miami., Barcelona, Shanghai, Sh...   [1, 0, 0, 0, 1, 0]  [False, False, False, True, False, False]   0.0
5   A   Shanghai    1   5           [Miami, Miami, Miami., Barcelona, Barc elona, ...   [1, 0, 0, 0, 0, 0]  [False, False, False, False, False, True]   0.0
6   A   Shangai     0   6           [Miami, Miami, Miami., Barcelona, Barc elona, ...   [1, 0, 0, 0, 0, 1]  [False, False, False, False, False, True]   1.0
7   B   Miami       1   0           [Miami, Miami., Barcelona, Barc elona, Shangha...   [1, 1, 0, 0, 1, 0]  [True, True, False, False, False, False]    1.0
8   B   Miami       1   1           [Miami, Miami., Barcelona, Barc elona, Shangha...   [1, 1, 0, 0, 1, 0]  [True, True, False, False, False, False]    1.0
9   B   Miami.      1   2           [Miami, Miami, Barcelona, Barc elona, Shanghai...   [1, 1, 0, 0, 1, 0]  [True, True, False, False, False, False]    1.0
10  B   Barcelona   0   3           [Miami, Miami, Miami., Barc elona, Shanghai, S...   [1, 1, 1, 0, 1, 0]  [False, False, False, True, False, False]   0.0
11  B   Barc elona  0   4           [Miami, Miami, Miami., Barcelona, Shanghai, Sh...   [1, 1, 1, 0, 1, 0]  [False, False, False, True, False, False]   0.0
12  B   Shanghai    1   5           [Miami, Miami, Miami., Barcelona, Barc elona, ...   [1, 1, 1, 0, 0, 0]  [False, False, False, False, False, True]   0.0
13  B   Shangai     0   6           [Miami, Miami, Miami., Barcelona, Barc elona, ...   [1, 1, 1, 0, 0, 1]  [False, False, False, False, False, True]   1.0

Для обновленного вопроса просто удалите часть кода, которая уточняет списки

df = pd.DataFrame({'col1':['A', 'A', 'A', 'A', 'A', 'A', 'A', 
                           'B', 'B', 'B', 'B', 'B', 'B', 'B'], 
                  'col2':['Miami', 'Miami', 'Miami.', 'Barcelona', 'Barc elona', 
                         'Shanghai', 'Shangai', 'Miami', 'Miami', 'Miami.', 
                         'Barcelona', 'Barc elona', 'Shanghai', 'Shangai'], 
                  'col3':[1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0]})


df['col2_list'] = df['col1'].map(df.groupby('col1')['col2'].apply(list))
df['col3_list'] = df['col1'].map(df.groupby('col1')['col3'].apply(list))

df['key'] = df.apply(lambda x: 
         np.array([fuzz.partial_ratio(x['col2'], el) for el in x['col2_list']]) >= 80, axis=1)

df['result'] = df.apply(lambda x: np.mean(np.array(x['col3_list'])[x['key']]), axis=1)

df

  col1  col2     col3   col2_list                                           col3_list               key                                             result
0   A   Miami       1   [Miami, Miami, Miami., Barcelona, Barc elona, ...   [1, 0, 0, 0, 0, 1, 0]   [True, True, True, False, False, False, False]  0.333333
1   A   Miami       0   [Miami, Miami, Miami., Barcelona, Barc elona, ...   [1, 0, 0, 0, 0, 1, 0]   [True, True, True, False, False, False, False]  0.333333
2   A   Miami.      0   [Miami, Miami, Miami., Barcelona, Barc elona, ...   [1, 0, 0, 0, 0, 1, 0]   [True, True, True, False, False, False, False]  0.333333
3   A   Barcelona   0   [Miami, Miami, Miami., Barcelona, Barc elona, ...   [1, 0, 0, 0, 0, 1, 0]   [False, False, False, True, True, False, False] 0.000000
4   A   Barc elona  0   [Miami, Miami, Miami., Barcelona, Barc elona, ...   [1, 0, 0, 0, 0, 1, 0]   [False, False, False, True, True, False, False] 0.000000
5   A   Shanghai    1   [Miami, Miami, Miami., Barcelona, Barc elona, ...   [1, 0, 0, 0, 0, 1, 0]   [False, False, False, False, False, True, True] 0.500000
6   A   Shangai     0   [Miami, Miami, Miami., Barcelona, Barc elona, ...   [1, 0, 0, 0, 0, 1, 0]   [False, False, False, False, False, True, True] 0.500000
7   B   Miami       1   [Miami, Miami, Miami., Barcelona, Barc elona, ...   [1, 1, 1, 0, 0, 1, 0]   [True, True, True, False, False, False, False]  1.000000
8   B   Miami       1   [Miami, Miami, Miami., Barcelona, Barc elona, ...   [1, 1, 1, 0, 0, 1, 0]   [True, True, True, False, False, False, False]  1.000000
9   B   Miami.      1   [Miami, Miami, Miami., Barcelona, Barc elona, ...   [1, 1, 1, 0, 0, 1, 0]   [True, True, True, False, False, False, False]  1.000000
10  B   Barcelona   0   [Miami, Miami, Miami., Barcelona, Barc elona, ...   [1, 1, 1, 0, 0, 1, 0]   [False, False, False, True, True, False, False] 0.000000
11  B   Barc elona  0   [Miami, Miami, Miami., Barcelona, Barc elona, ...   [1, 1, 1, 0, 0, 1, 0]   [False, False, False, True, True, False, False] 0.000000
12  B   Shanghai    1   [Miami, Miami, Miami., Barcelona, Barc elona, ...   [1, 1, 1, 0, 0, 1, 0]   [False, False, False, False, False, True, True] 0.500000
13  B   Shangai     0   [Miami, Miami, Miami., Barcelona, Barc elona, ...   [1, 1, 1, 0, 0, 1, 0]   [False, False, False, False, False, True, True] 0.500000
...