Python / Pandas / Spacy - 迭代DataFrame并计算pos_标签数

3

我有一个Pandas数据框,其中包含来自作者的一些文本,并希望对不同单词类型的总数进行一些统计处理。

数据框 - 我的数据:

>>> data
             name                   style                                              text     year       year_dt
number  
0001    Demetrius                       D   Demetrius an der russischen Grenze Er ist vo...     1805    1805-01-01
0002    Der versöhnte Menschenfeind     D   Der versöhnte Menschenfeind -Fragment Gegend...     1790    1790-01-01
0003    Die Braut von Messina           D   Die Braut von Messina oder die feindlichen B...     1803    1803-01-01

几个月前,我写了一个函数,它从df的每一行迭代,获取“书”的名称和内容,使用spacy进行词性标注,并计算名词、形容词和动词的数量。之后,将这个数字存储在新列中。

我的函数:

import spacy
from spacy.lang.de import German
from collections import defaultdict
nlp = spacy.load('de')

def calculate_the_word_types(data):
    nouns = defaultdict(lambda: 0)
    verbs = defaultdict(lambda: 0)
    adjectives = defaultdict(lambda: 0)

    # count all tokens, but not the punctuations
    for i, row in data.iterrows():
        doc = nlp(row["name"] + " " + row["text"])
    data.set_value(i, "nr_token", len(list(map(lambda x: x.text, 
                                     filter(lambda x: x.pos_ != 'PUNCT', doc)))))

    # count only the adjectives
    for a in map(lambda x: x.lemma_, filter(lambda x: x.pos_ == 'ADJ', doc)):
        adjectives[a] += 1
    data.set_value(i, "nr_adj", len(list(map(lambda x: x.text, 
                                     filter(lambda x: x.pos_ == 'ADJ', doc)))))  

    # count only the nouns
    for n in map(lambda x: x.lemma_, filter(lambda x: x.pos_ == 'NOUN', doc)):
        nouns[n] +=1
    data.set_value(i, "nr_noun", len(list(map(lambda x: x.text, 
                                     filter(lambda x: x.pos_ == 'NOUN', doc)))))

    # count only the verbs
    for v in map(lambda x: x.lemma_, filter(lambda x: (x.pos_ == 'AUX') | (x.pos_ == 'VERB'), doc)):
        verbs[v] += 1
    data.set_value(i, "nr_verb", len(list(map(lambda x: x.text, 
                                     filter(lambda x: (x.pos_ == 'AUX') | (x.pos_ == 'VERB'), doc)))))  

    return data

输出

>>> data
           name style      text     year       year_dt  nr_token  br_adj   nr_noun   nr_verb
number  
0001    Deme...     D   Deme...     1805    1805-01-01       NaN     NaN       NaN       NaN
0002    Der ...     D   Der ...     1790    1790-01-01       NaN     NaN       NaN       NaN
0003    Die ...     D   Die ...     1803    1803-01-01    7127.0   584.0    1328.0    1286.0

我认为这在以前是有效的,但现在不行了。因为我的函数输出如下,通过测试我知道它是有效的,但数字总是只在最后一行,所以它会覆盖自己,我想。

哪里出了问题?欢迎提供任何建议来改进此函数或可能更简单的解决方案!


1
问题在于您在循环中迭代 i,然后在循环外部基于 i 设置所有值,因此当然只有最后一行会被设置。 - ALollz
1个回答

3

将您的setter缩进,使其位于外部for循环内。

# count all tokens, but not the punctuations
for i, row in data.iterrows():
    doc = nlp(row["name"] + " " + row["text"])
    data.set_value(i, "nr_token", len(list(map(lambda x: x.text, 
                                 filter(lambda x: x.pos_ != 'PUNCT', doc)))))

    # count only the adjectives
    for a in map(lambda x: x.lemma_, filter(lambda x: x.pos_ == 'ADJ', doc)):
        adjectives[a] += 1
    data.set_value(i, "nr_adj", len(list(map(lambda x: x.text, 
                                 filter(lambda x: x.pos_ == 'ADJ', doc)))))  

    # count only the nouns
    for n in map(lambda x: x.lemma_, filter(lambda x: x.pos_ == 'NOUN', doc)):
        nouns[n] +=1
    data.set_value(i, "nr_noun", len(list(map(lambda x: x.text, 
                                 filter(lambda x: x.pos_ == 'NOUN', doc)))))

    # count only the verbs
    for v in map(lambda x: x.lemma_, filter(lambda x: (x.pos_ == 'AUX') | (x.pos_ == 'VERB'), doc)):
        verbs[v] += 1
    data.set_value(i, "nr_verb", len(list(map(lambda x: x.text, 
                                 filter(lambda x: (x.pos_ == 'AUX') | (x.pos_ == 'VERB'), doc)))))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接