Средняя "оценка" каждой строки pd.Serie на основе его содержимого, сопоставленного с помощью другой серии оценок - PullRequest
0 голосов
/ 22 февраля 2019

У меня есть (очень большая) серия, содержащая ключевые слова (каждая строка содержит несколько ключевых слов, разделенных '-', например,

In[5]: word_series
Out[5]: 
0    the-cat-is-pink
1           blue-sea
2      best-job-ever
dtype: object

У меня есть другая серия, которая содержит атрибуты оценки для каждого слова(слова - это индекс, оценки - это значения), например:

In[7]: all_scores
Out[7]: 
the     0.34
cat     0.56
best    0.01
ever    0.77
is      0.12
pink    0.34
job     0.01
sea     0.87
blue    0.65
dtype: float64

Все слова из моих слов word_series появляются в моих результатах. Я пытаюсь найти самый быстрый способ приписать оценкукаждая строка word_series, основанная на средней оценке каждого из ее слов из all_scores. Если строка не указана, оценка должна быть средней из оценок.

Я пытался использовать применить этот способ, но этоЭто было слишком медленно.

scores = word_series.apply(
        lambda x: all_scores[x.split('-')].mean()).fillna(
        all_scores.mean())

Затем я подумал, что могу разбить all_words на столбцы, используя str.replace, и, возможно, выполнить операцию типа умножения матриц, используя эту новую матрицу M и мои слова, такие как M.mul (all_scores)где каждая строка в M сопоставляется со значениями, основанными на индексе all_scores. Это был бы первый шаг, чтобы получить среднее значение, которое я мог бы затем разделить на число of non-na в каждой строке

In[9]: all_words.str.split('-', expand=True)
Out[9]: 
      0    1     2     3
0   the  cat    is  pink
1  blue  sea  None  None
2  best  job  ever  None

Возможна ли такая операция?Или есть другой быстрый способ добиться этого?

Ответы [ 2 ]

0 голосов
/ 22 февраля 2019

вот путь

печать (а)

             words
0  the-cat-is-pink
1         blue-sea
2    best-job-ever

печать (б)

      all_scores
the         0.34
cat         0.56
best        0.01
ever        0.77
is          0.12
pink        0.34
job         0.01
sea         0.87
blue        0.65

b = b.reset_index()

печать (б)

  index  all_scores
0   the        0.34
1   cat        0.56
2  best        0.01
3  ever        0.77
4    is        0.12
5  pink        0.34
6   job        0.01
7   sea        0.87
8  blue        0.65

a['score'] = a['words'].str.split('-').apply(lambda x: sum([b[b['index'] == w].reset_index()['all_scores'][0] for w in x])/len(x))

вывод

             words     score
0  the-cat-is-pink  0.340000
1         blue-sea  0.760000
2    best-job-ever  0.263333
0 голосов
/ 22 февраля 2019

Работа со строковыми данными медленна в пандах, поэтому используйте понимание списка с картой по Series и mean:

from statistics import mean

L = [mean(all_scores.get(y) for y in x.split('-')) for x in word_series]
a = pd.Series(L, index=word_series.index)
print (a)

0    0.340000
1    0.760000
2    0.263333
dtype: float64

Или:

def mean(a):
    return sum(a) / len(a)

L = [mean([all_scores.get(y) for y in x.split('-')]) for x in word_series]
a = pd.Series(L, index=word_series.index)

Если возможно, некоторыеДля несоответствующих значений добавьте параметр np.nan к get и используйте numpy.nanmean:

L = [np.nanmean([all_scores.get(y, np.nan) for y in x.split('-')]) for x in word_series]
a = pd.Series(L, index=word_series.index)

Или:

def mean(a):
    return sum(a) / len(a)

L = [mean([all_scores.get(y, np.nan) for y in x.split('-') if y in all_scores.index]) 
      for x in word_series]
...