Cómo aplicar pos_tag_sents () a pandas dataframe de manera eficiente

En situaciones en las que desea etiquetar en POS una columna de texto almacenada en un dataframe de pandas con 1 oración por fila, la mayoría de las implementaciones en SO utilizan el método de aplicación

dfData['POSTags']= dfData['SourceText'].apply( lamda row: [pos_tag(word_tokenize(row) for item in row]) 

La documentación de NLTK recomienda usar pos_tag_sents () para etiquetar de manera eficiente más de una oración.

¿Se aplica eso a este ejemplo y, de ser así, el código sería tan simple como cambiar pso_tag a pos_tag_sents o pos_tag_sents significa fonts de texto de los párrafos?

Como se mencionó en los comentarios, pos_tag_sents() apunta a reducir la carga del preceptor cada vez, pero el problema es ¿cómo hacer esto y aún producir una columna en un dataframe de pandas?

Enlace al conjunto de datos de muestra 20kRows

Entrada

 $ cat test.csv ID,Task,label,Text 1,Collect Information,no response,cozily married practical athletics Mr. Brown flat 2,New Credit,no response,active married expensive soccer Mr. Chang flat 3,Collect Information,response,healthy single expensive badminton Mrs. Green flat 4,Collect Information,response,cozily married practical soccer Mr. Brown hierachical 5,Collect Information,response,cozily single practical badminton Mr. Brown flat 

TL; DR

 >>> from nltk import word_tokenize, pos_tag, pos_tag_sents >>> import pandas as pd >>> df = pd.read_csv('test.csv', sep=',') >>> df['Text'] 0 cozily married practical athletics Mr. Brown flat 1 active married expensive soccer Mr. Chang flat 2 healthy single expensive badminton Mrs. Green ... 3 cozily married practical soccer Mr. Brown hier... 4 cozily single practical badminton Mr. Brown flat Name: Text, dtype: object >>> texts = df['Text'].tolist() >>> tagged_texts = pos_tag_sents(map(word_tokenize, texts)) >>> tagged_texts [[('cozily', 'RB'), ('married', 'JJ'), ('practical', 'JJ'), ('athletics', 'NNS'), ('Mr.', 'NNP'), ('Brown', 'NNP'), ('flat', 'JJ')], [('active', 'JJ'), ('married', 'VBD'), ('expensive', 'JJ'), ('soccer', 'NN'), ('Mr.', 'NNP'), ('Chang', 'NNP'), ('flat', 'JJ')], [('healthy', 'JJ'), ('single', 'JJ'), ('expensive', 'JJ'), ('badminton', 'NN'), ('Mrs.', 'NNP'), ('Green', 'NNP'), ('flat', 'JJ')], [('cozily', 'RB'), ('married', 'JJ'), ('practical', 'JJ'), ('soccer', 'NN'), ('Mr.', 'NNP'), ('Brown', 'NNP'), ('hierachical', 'JJ')], [('cozily', 'RB'), ('single', 'JJ'), ('practical', 'JJ'), ('badminton', 'NN'), ('Mr.', 'NNP'), ('Brown', 'NNP'), ('flat', 'JJ')]] >>> df['POS'] = tagged_texts >>> df ID Task label \ 0 1 Collect Information no response 1 2 New Credit no response 2 3 Collect Information response 3 4 Collect Information response 4 5 Collect Information response Text \ 0 cozily married practical athletics Mr. Brown flat 1 active married expensive soccer Mr. Chang flat 2 healthy single expensive badminton Mrs. Green ... 3 cozily married practical soccer Mr. Brown hier... 4 cozily single practical badminton Mr. Brown flat POS 0 [(cozily, RB), (married, JJ), (practical, JJ),... 1 [(active, JJ), (married, VBD), (expensive, JJ)... 2 [(healthy, JJ), (single, JJ), (expensive, JJ),... 3 [(cozily, RB), (married, JJ), (practical, JJ),... 4 [(cozily, RB), (single, JJ), (practical, JJ), ... 

En largo:

Primero, puedes extraer la columna de Text a una lista de cadenas:

 texts = df['Text'].tolist() 

Luego puedes aplicar la función word_tokenize :

 map(word_tokenize, texts) 

Tenga en cuenta que, la sugerencia de @Boud es casi la misma, utilizando df.apply :

 df['Text'].apply(word_tokenize) 

A continuación, vuelca el texto con token en una lista de cadenas:

 df['Text'].apply(word_tokenize).tolist() 

Entonces puedes usar pos_tag_sents :

 pos_tag_sents( df['Text'].apply(word_tokenize).tolist() ) 

A continuación, agregue la columna de nuevo al dataframe:

 df['POS'] = pos_tag_sents( df['Text'].apply(word_tokenize).tolist() ) 

Al aplicar pos_tag en cada fila, el modelo de Perceptron se cargará cada vez (operación costosa, ya que lee una salmuera del disco).

Si en cambio obtiene todas las filas y las envía a pos_tag_sents (que toma la list(list(str)) ), el modelo se carga una vez y se usa para todos.

Vea la fuente .

Asigne esto a su nueva columna en su lugar:

 dfData['POSTags'] = pos_tag_sents(dfData['SourceText'].apply(word_tokenize).tolist())