Сравнение текста со списком для нескольких файлов с использованием функции и для циклов - PullRequest
0 голосов
/ 27 января 2019

Моя конечная цель - создать цикл for, который обрабатывает несколько файлов, с дополнительным циклом for, который сравнивает индекс терминов с фреймом данных.Чтобы сделать это более увлекательным, я также включил функцию, поскольку мне, вероятно, придется применить тот же принцип к другой переменной в том же фрейме данных.Есть несколько проблем.

  1. Я не уверен, должен ли я использовать регулярное выражение в этом случае или достаточно простого оператора in.
  2. Метод, который я использую, неэффективен (не говоря уже о том, что он не работает).Я надеялся, что есть что-то вроде оператора isin, но каждое слово в списке нужно проверять по одной строке фрейма данных.Тем не менее, я не уверен, как применять его, когда я пытаюсь сделать что-то вроде этого ...
df:    
     'headline'                                                'source'
     targets is making better stars in the bucks               target news
     more diamonds than rocks in saturn rings                  wishful thinking
     diamond in the rough employees take too many naps         refresh sleep

data:
      'company'
      targets 
      stars in the bucks
      wallymarty
      velocity global
      diamond in the rough

ccompanies = data['company'].tolist() #convert into list 
def find(x): #function to compare df['headline'] against list of companies
    result = []
    companies = set(ccompanies) #edit based on comment, saves time
    for i in companies:
        if i in x:
            result.append(x)
    return result

matches = df['headline'].apply(find)

Желаемый вывод будет список заголовков, которые соответствуют компании: targets is making better stars in the bucks diamond in the rough employees take too many naps

РЕДАКТИРОВАТЬ: Мой скрипт был отредактирован, так что теперь он работает и показывает заголовки.Однако вместо только желаемого вывода выходные данные показывают все строки фрейма данных с заполнением только применимых строк.

Ответы [ 2 ]

0 голосов
/ 27 января 2019

В чистых пандах без итерации и преобразования в список.

Сначала присоедините data к df так, чтобы заголовок "реплицировался" для каждого сравниваемого названия компании.Для облегчения этого соединения используется временный столбец «ключ».

In [60]: data_df = data.to_frame()

In [61]: data_df['key'] = 1

In [63]: df['key'] = 1

In [65]: merged = pd.merge(df, data_df, how='outer', on='key').drop('key', axis=1)

merged будет выглядеть следующим образом.Как видите, в зависимости от размера data, вы можете получить огромный DataFrame с помощью этого метода.

In [66]: merged
Out[66]:
                                             headline            source               company
0         targets is making better stars in the bucks       target news               targets
1         targets is making better stars in the bucks       target news    stars in the bucks
2         targets is making better stars in the bucks       target news            wallymarty
3         targets is making better stars in the bucks       target news       velocity global
4         targets is making better stars in the bucks       target news  diamond in the rough
5            more diamonds than rocks in saturn rings  wishful thinking               targets
6            more diamonds than rocks in saturn rings  wishful thinking    stars in the bucks
7            more diamonds than rocks in saturn rings  wishful thinking            wallymarty
8            more diamonds than rocks in saturn rings  wishful thinking       velocity global
9            more diamonds than rocks in saturn rings  wishful thinking  diamond in the rough
10  diamond in the rough employees take too many naps     refresh sleep               targets
11  diamond in the rough employees take too many naps     refresh sleep    stars in the bucks
12  diamond in the rough employees take too many naps     refresh sleep            wallymarty
13  diamond in the rough employees take too many naps     refresh sleep       velocity global
14  diamond in the rough employees take too many naps     refresh sleep  diamond in the rough

Затем найдите текст в заголовке.Если найдено, помещает True в новый столбец "found", в противном случае - False.

In [67]: merged['found'] = merged.apply(lambda x: x['company'] in x['headline'], axis=1)

Затем удаляет заголовки, в которых совпадений не найдено:

In [68]: found_df = merged.drop(merged[merged['found']==False].index)

In [69]: found_df
Out[69]:
                                             headline         source               company  found
0         targets is making better stars in the bucks    target news               targets   True
1         targets is making better stars in the bucks    target news    stars in the bucks   True
14  diamond in the rough employees take too many naps  refresh sleep  diamond in the rough   True

При необходимости, суммируйтетолько заголовок и компания

In [70]: found_df[['headline', 'company']]
Out[70]:
                                             headline               company
0         targets is making better stars in the bucks               targets
1         targets is making better stars in the bucks    stars in the bucks
14  diamond in the rough employees take too many naps  diamond in the rough

Ярлык : Этапы 67 до конца можно суммировать с помощью этой команды

merged.drop(merged[merged.apply(lambda x: x['company'] in x['headline'], axis=1) == False].index)[['headline', 'source']]
0 голосов
/ 27 января 2019

... в этом случае следует использовать регулярное выражение или если достаточно простого оператора in?

Использование in вполне нормально, поскольку вы, по-видимому, нормализовались до .lower() и удалили пунктуацию.

Вы действительно должны попытаться использовать более значимые идентификаторы.Например, вместо i обычная идиома будет for company in companies:.

Вы выяснили, как использовать .tolist(), это хорошо.Но вы действительно хотите создать set, а не list, для поддержки эффективного теста in.Это разница между хешированным поиском O (1) и вложенным циклом для линейного сканирования списка.

Это не имеет особого смысла:

        for i in ccompanies:
            i = [x]

Вы начинаете итерацию, но затем i становится по существу константой?Там не совсем понятно, к чему вы стремились.

Если вы зайдете в этот проект немного дальше, вы можете рассмотреть возможность подбора компаний с NLTK или TfidfVectorizer из scikit-learn или https://pypi.org/project/fuzzywuzzy/

...