Найти частоту слов в фрейме данных из списка

#python #python-3.x #regex #pandas

#python #python-3.x #регулярное выражение #pandas

Вопрос:

 import pandas as pd
list = ['apple','banana','cherries','dragonfruit','elderberry']
data = {'name': ['Alpha', 'Bravo','Charlie','Delta','Echo'],
             'favorite_fruit':  ['apple banana cherries', 'banana cherries dragonfruit',
                           'cherries dragonfruit','dragonfruit','apple elderberry']}

df = pd.DataFrame (data, columns = ['name','favorite_fruit'])
  

Я хочу подсчитать частоту каждого фрукта в list в df.
Ожидаемый результат:

 df2
Fruit       | Frequency
Apple       |    2     
Banana      |    2
Cherries    |    3
Dragonfruit |    3
Elderberry  |    1
  

Код df.favorite_fruit.str.split(expand=True).stack().value_counts() работает для небольшого фрейма данных.
Если df.favorite_fruit содержит тысячи строк с различными комбинациями фруктов,
как мне найти только частоту слов в list ?

Ответ №1:

Возможно, это ответ с петлей, но вы можете просто отфильтровать значения из ответа, который вы уже описали. Итак, если вы начнете с этого:

 >>> df2 = df.favorite_fruit.str.split(expand=True).stack()
>>> df2

0  0          apple
   1         banana
   2       cherries
1  0         banana
   1       cherries
   2    dragonfruit
2  0       cherries
   1    dragonfruit
3  0    dragonfruit
4  0          apple
   1     elderberry
dtype: object
  

Вы могли бы использовать isin , чтобы ограничить данные теми, которые находятся в целевом списке:

 >>> target = ['apple', 'banana']
>>> df2[df2.isin(target)].value_counts()

banana    2
apple     2
dtype: int64
  

Или даже после вашего первоначального ответа:

 >>> df.favorite_fruit.str.split(expand=True).stack().value_counts().loc[target]

apple     2
banana    2
dtype: int64
  

Если проблема в том, что операции expand и stack являются дорогостоящими с таким количеством данных, то, возможно, это не будет удовлетворительным. Но я думаю, возможно, это может быть лучше, чем ответы на основе цикла?

Комментарии:

1. Использование первой части ответа-лазейки работает, но вторая часть кода df.favorite_fruit.str.split(expand=True).stack().value_counts().loc[target] возвращает ошибку ключа: «Передача списка-нравится » . loc или [] с отсутствующими метками больше не поддерживаются, ,см. pandas.pydata.org/pandas-docs/stable/user_guide /… ‘. Я изменил . loc в .reindex но это не работает. Вторая часть кода, если она работает, будет лучше, поскольку она не добавляет больше переменных..

2. @Luc хммм, у меня это работает — я копирую / вставляю эту строку сразу после вашей df = pd.DataFrame.... строки из вашего примера и не получаю ошибок (также с target = ['apple', 'banana'] определенным). Серия, возвращаемая value_counts() , должна иметь значения фруктов в качестве индекса, поэтому вы должны иметь возможность использовать loc с вашими названиями фруктов для индексации

3. возможно, это потому, что у меня отсутствуют метки в моих реальных данных. Тем не менее, если второе решение не работает. Подойдет первый, хотя тогда я создам много переменных. Спасибо!

4. pandas.pydata.org/pandas-docs/stable/user_guide/…

5. @Luc ahhh это в ваших реальных данных — эта ошибка должна означать, что одного из ваших целевых слов нет в фрейме данных / значение имеет значение — возможно ли это? Но в этом случае df.favorite_fruit.str.split(expand=True).stack().value_counts().reindex(target) работает и для меня.

Ответ №2:

Возможно, это немного окольный способ сделать это, но если ваш favorite_fruit столбец всегда разделен пробелом, что-то вроде этого должно сработать:

 import pandas as pd

list = ['apple','banana','cherries','dragonfruit','elderberry']
data = {'name': ['Alpha', 'Bravo','Charlie','Delta','Echo'],
             'favorite_fruit':  ['apple banana cherries', 'banana cherries dragonfruit',
                           'cherries dragonfruit','dragonfruit','apple elderberry']}

df = pd.DataFrame (data, columns = ['name','favorite_fruit'])

new_df = pd.DataFrame()
data = {}

for i, row in df.iterrows():
    s = row['favorite_fruit']
    items = s.split(' ')
    for item in items:
        if item in data.keys():
            data[item].append(1)
        else:
            data[item] = [1]

for key, value in data.items():
    data[key] = sum(value)

fruit = []
frequency = []

for key, value in data.items():
    fruit.append(key)
    frequency.append(value)

new_df = pd.DataFrame({'fruit': fruit, 'frequency':frequency})
print(new_df)
  

При этом выводится следующее:

          fruit  frequency
0        apple          2
1       banana          2
2     cherries          3
3  dragonfruit          3
4   elderberry          1
  

Комментарии:

1. извините, это близко, но не совсем подходит для моей «реальной» проблемы. favorite_fruit — это строка, содержащая предложение, которое иногда содержит запятую и смайлики. Приведенный выше код дает мне частоту всех слов в favorite_fruit столбце, а не только частоту слов в list .

2. Что ж, тогда вам нужно обновить и отредактировать свой минимальный рабочий пример, чтобы отразить это … иначе мы не сможем вам помочь…

Ответ №3:

Попробуйте использовать функцию разнесения после разделения.

 df.favorite_fruit.str.split().explode().value_counts()

cherries       3
dragonfruit    3
banana         2
apple          2
elderberry     1
Name: favorite_fruit, dtype: int64