Una forma más rápida de eliminar las palabras de parada en Python

Estoy tratando de eliminar las palabras clave de una cadena de texto:

from nltk.corpus import stopwords text = 'hello bye the the hi' text = ' '.join([word for word in text.split() if word not in (stopwords.words('english'))]) 

Estoy procesando 6 mil de esas cuerdas, así que la velocidad es importante. Perfilando mi código, la parte más lenta son las líneas de arriba, ¿hay una mejor manera de hacer esto? Estoy pensando en usar algo como re.sub de regex pero no sé cómo escribir el patrón para un conjunto de palabras. Alguien me puede ayudar y también estoy feliz de escuchar otros métodos posiblemente más rápidos.

Nota: stopwords.words('english') la sugerencia de alguien de envolver stopwords.words('english') con set() pero eso no hizo ninguna diferencia.

Gracias.

Intente almacenar en caché el objeto de palabras clave, como se muestra a continuación. Construir esto cada vez que llamas a la función parece ser el cuello de botella.

  from nltk.corpus import stopwords cachedStopWords = stopwords.words("english") def testFuncOld(): text = 'hello bye the the hi' text = ' '.join([word for word in text.split() if word not in stopwords.words("english")]) def testFuncNew(): text = 'hello bye the the hi' text = ' '.join([word for word in text.split() if word not in cachedStopWords]) if __name__ == "__main__": for i in xrange(10000): testFuncOld() testFuncNew() 

Corrí esto a través del generador de perfiles: python -m cProfile -s cumulative test.py. Las líneas relevantes se publican a continuación.

n Tiempo de acumulación acumulativo

10000 7.723 palabras.py:7 (testfuncOld)

10000 0.140 words.py:11(testFuncNew)

Por lo tanto, el almacenamiento en caché de la instancia de palabras clave da una aceleración de ~ 70x.

Use una expresión regular para eliminar todas las palabras que no coincidan:

 import re pattern = re.compile(r'\b(' + r'|'.join(stopwords.words('english')) + r')\b\s*') text = pattern.sub('', text) 

Es probable que esto sea mucho más rápido que el bucle, especialmente para cadenas de entrada grandes.

Si la última palabra en el texto se elimina por esto, es posible que haya espacios en blanco al final. Propongo manejar esto por separado.

Primero, estás creando palabras de parada para cada cadena. Crealo una vez. Set sería genial aquí de hecho.

 forbidden_words = set(stopwords.words('english')) 

Más tarde, deshacerse de [] dentro de join . Use generador en su lugar.

 ' '.join([x for x in ['a', 'b', 'c']]) 

reemplazar a

 ' '.join(x for x in ['a', 'b', 'c']) 

Lo siguiente a tratar sería hacer que .split() produzca valores en lugar de devolver una matriz. Creo que regex sería un buen reemplazo aquí. Vea esta explicación para saber por qué s.split() es realmente rápido.

Por último, realice un trabajo de este tipo en paralelo (elimine las palabras de parada en cadenas de 6 m). Ese es un tema completamente diferente.

Lo siento por la respuesta tardía. Sería útil para los nuevos usuarios.

  • Crear un diccionario de palabras clave utilizando la biblioteca de colecciones.
  • Use ese diccionario para una búsqueda muy rápida (tiempo = O (1)) en lugar de hacerlo en la lista (tiempo = O (palabras clave))

     from collections import Counter stop_words = stopwords.words('english') stopwords_dict = Collections.counter(stop_words) text = ' '.join([word for word in text.split() if stopwords_dict[word]==0])