Самый быстрый способ получить количество строк строк, содержащих подстроку в python, между двумя фреймами данных

#python #python-3.x #pandas #nltk

#python #python-3.x #pandas #nltk

Вопрос:

У меня есть два фрейма данных, в 1 есть слова, а в другом — текст. Я хочу получить количество всех строк, содержащих слово в первом фрейме данных.

Word =

 ID   | Word
------------
1    | Introduction
2    | database
3    | country 
4    | search
  

Текст =

 ID   | Text
------------
1    | Introduction to python
2    | sql is a database
3    | Introduction to python in our country
4    | search for a python teacher in our country
  

В качестве конечного результата я хочу

 ID   | Word  |  Count
---------------------
1    | Introduction  | 2
2    | database  | 1
3    | country  |  1
4    | search  |  2
  

У меня есть 200000 строк в слове df и 55000 строк в тексте (длина каждого текста составляет около 2000 слов) df. Для завершения всего процесса с помощью приведенного ниже кода требуется около 76 часов

»’

 def docCount(docdf, worddf):
    final_dict = {}
    for i in tqdm(worddf.itertuples()):
        docdf["Count"] = docdf.Text.str.contains(i[2])
        temp_dict = {i[2]: docdf.Count.sum()}
        final_dict = dict(Counter(final_dict) Counter(temp_dict))
    return final_dict
  

»’

Ответ №1:

Вот простое решение

 world_count = pd.DataFrame(
    {'words': Word['Word'].tolist(),
     'count': [Text['Text'].str.contains(w).sum() for w in words],
    }).rename_axis('ID')
  

Вывод:

 world_count.head()

'''
           words  count
ID                     
0   Introduction      2
1       database      1
2        country      2
3         search      1
'''
  

Пошаговое решение:

 # Convert column to list
words = Word['Word'].tolist()

# Get the count
count = [Text['Text'].str.contains(w).sum() for w in words]

world_count = pd.DataFrame(
    {'words': words,
     'count': count,
    }).rename_axis('ID')
  

Совет:

Я бы посоветовал вам преобразовать в нижний регистр, чтобы вы не пропустили ни одного счета из-за верхнего / нижнего регистра

 import re
import pandas as pd

world_count = pd.DataFrame(
    {'words': Word['Word'].str.lower().str.strip().tolist(),
     'count': [Text['Text'].str.contains(w,flags=re.IGNORECASE, regex=True).sum() for w in words],
    }).rename_axis('ID')
  

Ответ №2:

Вы можете попробовать этот пример, чтобы ускорить процесс:

 df1 = pd.DataFrame({'Word':['Introduction', 'database', 'country', 'search']})
df2 = pd.DataFrame({'Text':['Introduction to python', 'sql is a database', 'Introduction to python in our country', 'search for a python teacher in our country']})

tmp = pd.DataFrame(df2['Text'].str.split().explode()).set_index('Text').assign(c=1)
tmp = tmp.groupby(tmp.index)['c'].sum()
print( df1.merge(tmp, left_on='Word', right_on=tmp.index) )
  

С принтами:

            Word  c
0  Introduction  2
1      database  1
2       country  2
3        search  1
  

Ответ №3:

Используйте Series.str.split with Series.explode для последовательности слов:

 s = df2['Text'].str.split().explode()
#oldier pandas versions
#s = df2['Text'].str.split(expand=True).stack()
  

Затем фильтруйте только совпадающие значения по Series.isin и boolean indexing , count by Series.value_counts и last use DataFrame.join :

 df1 = df1.join(s[s.isin(df1['Word'])].value_counts().rename('Count'), on='Word')
print (df1)
           Word  Count
0  Introduction      2
1      database      1
2       country      2
3        search      1