Tenho uma coluna no Pandas DataFrame(Nomes) com uma grande coleção de nomes. Tenho outra coluna de texto DataFrame(Título) e, entre os textos, os nomes no quadro Nome estão lá. Qual seria a maneira mais rápida de extrair nomes correspondentes do Título? A imagem abaixo mostra meu trabalho até agora, e é muito lento para o grande conjunto de dados atual.
import pandas as pd
import re
Names = pd.DataFrame({
'ENTITY_NAME': ['XYZ', 'ABC', 'NGA', 'METRO','DPAC']
})
Titles = pd.DataFrame({
'title': ['testing some text XYZ testing some text.',
'XYZ, ABC some random text',
'some text DPAC random random']
})
# Function to extract ENTITY_NAME if found in title
def extract_entity_name(title, entity_names):
pattern = '|'.join([r'\b' + re.escape(entity) + r'\b' for entity in entity_names])
matches = re.findall(pattern, title)
return ', '.join(matches)
Titles['extracted_entity_name'] = Titles['title'].apply(lambda x: extract_entity_name(x, Names['ENTITY_NAME'].tolist()))
display(Titles.head())
Seu código é lento porque você está recriando o padrão para cada linha, mesmo que seja o mesmo, e porque você está usando
apply
.Você pode acelerar isso definindo a regex apenas uma vez:
Dependendo do comprimento do DataFrame, você pode acelerá-lo usando uma compreensão de lista:
Saída:
Horários:
O principal erro no seu código foi não usar o método vetorizado .str.contains. Ele é um código C pré-compilado e busca todas as linhas "de uma só vez" com uma única chamada, evitando assim um loop Python que gera uma sobrecarga relativamente grande. Além disso, seu código original recompila a expressão regular para cada nome de cada título. Pelo que entendi, isso é perda de tempo, pois os nomes não mudam, então a expressão regular também não muda. Podemos compilar a expressão regular para cada nome uma única vez e usá-la repetidamente.
Obrigado por fornecer o que você fez até agora, em vez de apenas descrever o problema que estava tendo e esperar que alguém o fizesse por você. Mesmo que você tenha descrito seu caso de uso perfeitamente, o código fornecido deixou muito mais claro o que você estava tentando realizar e por que estava tendo problemas.
Por favor, responda com um comentário se ainda estiver com problemas de desempenho do código. Existem bibliotecas que podem fornecer métodos mais eficientes para isso, mas implementá-los é muito mais complicado do que as otimizações acima, e acredito que essas mudanças serão a maior melhoria em relação ao esforço para implementá-las.