Recorriendo una lista de bigramas para buscar, necesito crear un campo booleano para cada bigrama según si está presente o no en una serie de pandas tokenizados. ¡Y agradecería un voto a favor si crees que esta es una buena pregunta!
Lista de bigramas:
bigrams = ['data science', 'computer science', 'bachelors degree']Marco de datos:
df = pd.DataFrame(data={'job_description': [['data', 'science', 'degree', 'expert'], ['computer', 'science', 'degree', 'masters'], ['bachelors', 'degree', 'computer', 'vision'], ['data', 'processing', 'science']]})Salida deseada:
job_description data science computer science bachelors degree 0 [data, science, degree, expert] True False False 1 [computer, science, degree, masters] False True False 2 [bachelors, degree, computer, vision] False False True 3 [data, bachelors, science] False False FalseCriterios:
Lo que he probado:
Error: df = [x for x in df['job_description'] if x in bigrams]
Error: df[bigrams] = [[any(w==term for w in lst) for term in bigrams] for lst in df['job_description']]
Error: no se pudo adaptar el enfoque aquí -> Hacer coincidir trigramas, bigramas y unigramas con un texto; si unigrama o bigrama es una subcadena de un trigrama ya emparejado, pasa; pitón
Error: tampoco se pudo adaptar este -> Comparar dos listas de bigramas y devolver el bigrama coincidente
Falló: este método está muy cerca , pero no pudo adaptarse a bigramas -> Crear nuevos campos booleanos basados en términos específicos que aparecen en un marco de datos de pandas tokenizados
¡Gracias por cualquier ayuda que usted nos pueda proporcionar!
También puede intentar usar numpy y nltk , que deberían ser bastante rápidos:
import pandas as pd import numpy as np import nltk bigrams = ['data science', 'computer science', 'bachelors degree'] df = pd.DataFrame(data={'job_description': [['data', 'science', 'degree', 'expert'], ['computer', 'science', 'degree', 'masters'], ['bachelors', 'degree', 'computer', 'vision'], ['data', 'processing', 'science']]}) def find_bigrams(data): output = np.zeros((data.shape[0], len(bigrams)), dtype=bool) for i, d in enumerate(data): possible_bigrams = [' '.join(x) for x in list(nltk.bigrams(d)) + list(nltk.bigrams(d[::-1]))] indices = np.where(np.isin(bigrams, list(set(bigrams).intersection(set(possible_bigrams))))) output[i, indices] = True return list(output.T) output = find_bigrams(df['job_description'].to_numpy()) df = df.assign(**dict(zip(bigrams, output))) | | job_description | data science | computer science | bachelors degree | |---:|:----------------------------------------------|:---------------|:-------------------|:-------------------| | 0 | ['data', 'science', 'degree', 'expert'] | True | False | False | | 1 | ['computer', 'science', 'degree', 'masters'] | False | True | False | | 2 | ['bachelors', 'degree', 'computer', 'vision'] | False | False | True | | 3 | ['data', 'processing', 'science'] | False | False | False |Podrías usar una expresión regular y extractall :
regex = '|'.join('(%s)' % b.replace(' ', r'\s+') for b in bigrams) matches = (df['job_description'].apply(' '.join) .str.extractall(regex).droplevel(1).notna() .groupby(level=0).max() ) matches.columns = bigrams out = df.join(matches).fillna(False)producción:
job_description data science computer science bachelors degree 0 [data, science, degree, expert] True False False 1 [computer, science, degree, masters] False True False 2 [bachelors, degree, computer, vision] False False True 3 [data, processing, science] False False Falseexpresión regular generada:
'(data\\s+science)|(computer\\s+science)|(bachelors\\s+degree)'