【问题标题】:Stripping proper nouns from text从文本中去除专有名词
【发布时间】:2018-06-14 16:07:21
【问题描述】:

我有一个包含数千行文本数据的 df。我正在使用 spaCy 在该 df 的单个列上执行一些 NLP,并尝试使用以下方法从我的文本数据中删除专有名词、停用词和标点符号:

tokens = []
lemma = []
pos = []

for doc in nlp.pipe(df['TIP_all_txt'].astype('unicode').values, batch_size=9845,
                        n_threads=3):
    if doc.is_parsed:
        tokens.append([n.text for n in doc if not n.is_punct and not n.is_stop and not n.is_space and not n.is_propn])
        lemma.append([n.lemma_ for n in doc if not n.is_punct and not n.is_stop and not n.is_space and not n.is_propn])
        pos.append([n.pos_ for n in doc if not n.is_punct and not n.is_stop and not n.is_space and not n.is_propn])
    else:
        tokens.append(None)
        lemma.append(None)
        pos.append(None)

df['s_tokens_all_txt'] = tokens
df['s_lemmas_all_txt'] = lemma
df['s_pos_all_txt'] = pos

df.head()

但我得到了这个错误,我不知道为什么:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-34-73578fd46847> in <module>()
      6                         n_threads=3):
      7     if doc.is_parsed:
----> 8         tokens.append([n.text for n in doc if not n.is_punct and not n.is_stop and not n.is_space and not n.is_propn])
      9         lemma.append([n.lemma_ for n in doc if not n.is_punct and not n.is_stop and not n.is_space and not n.is_propn])
     10         pos.append([n.pos_ for n in doc if not n.is_punct and not n.is_stop and not n.is_space and not n.is_propn])

<ipython-input-34-73578fd46847> in <listcomp>(.0)
      6                         n_threads=3):
      7     if doc.is_parsed:
----> 8         tokens.append([n.text for n in doc if not n.is_punct and not n.is_stop and not n.is_space and not n.is_propn])
      9         lemma.append([n.lemma_ for n in doc if not n.is_punct and not n.is_stop and not n.is_space and not n.is_propn])
     10         pos.append([n.pos_ for n in doc if not n.is_punct and not n.is_stop and not n.is_space and not n.is_propn])

AttributeError: 'spacy.tokens.token.Token' object has no attribute 'is_propn'

如果我取出 not n.is_propn,代码会按预期运行。我用谷歌搜索并阅读了 spaCy 文档,但到目前为止还没有找到答案。

【问题讨论】:

    标签: python python-3.x pandas spacy


    【解决方案1】:

    我在Token object 上看不到is_propn 属性。

    我认为您应该检查 词性类型为 PROPN (reference):

    from spacy.parts_of_speech import PROPN
    
    def is_proper_noun(token):
        if token.doc.is_tagged is False:  # check if the document was POS-tagged
            raise ValueError('token is not POS-tagged')
    
        return token.pos == PROPN
    

    【讨论】:

    • 这看起来只会显示标记为 propn 的标记,和/或为未标记的单词返回错误,而不是将它们从新的文本列中排除。我错过了什么吗?
    • @LMGagne 我在想你可以用这个函数代替is_propn,例如:[n.text for n in doc if not n.is_punct and not n.is_stop and not n.is_space and not is_proper_noun(n)]
    • 嗯,有道理。谢谢!
    【解决方案2】:

    添加到@alecxe 答案。

    没有需要

    • 一次性填充数据帧的所有行。
    • 在填充数据框时获取单独的标记、引理和 pos 列表。

    你可以试试:

    df = pd.DataFrame(columns=['tokens', 'lemmas', 'pos'])
    
    annotated_docs = nlp.pipe(df['TIP_all_txt'].astype('unicode').values,
                              batch_size=9845, n_threads=3)
    
    for doc in annotated_docs:
        if doc.is_parsed:
            # Remove the tokens that you don't want.
            tokens, lemmas, pos = zip(*[(tok.text, tok.lemma_, tok.pos_) 
                                        for tok in doc if not
                                        (tok.is_punct or tok.is_stop 
                                         or tok.is_space or is_proper_noun(tok) )
                                       ]
                                      )
            # Populate the DataFrame.
            df.append({'tokens':tokens, 'lemmas':lemmas, 'pos':pos})
    

    这是来自how to split column of tuples in pandas dataframe? 的更简洁的 pandas 技巧,但数据框会占用更多内存:

    df = pd.DataFrame(columns=['Tokens'])
    
    annotated_docs = nlp.pipe(df['TIP_all_txt'].astype('unicode').values,
                              batch_size=9845, n_threads=3)
    
    for doc in annotated_docs:
        if doc.is_parsed:
            # Remove the tokens that you don't want.
            df.append([(tok.text, tok.lemma_, tok.pos_) 
                        for tok in doc if not
                        (tok.is_punct or tok.is_stop 
                         or tok.is_space or is_proper_noun(tok) )
                       ]
                      )
    
    df[['tokens', 'lemmas', 'pos']] = df['Tokens'].apply(pd.Series)
    

    【讨论】:

      【解决方案3】:
      from nltk.tag import pos_tag
      def proper_nouns():
          tagged_sent = pos_tag(speech.split())
          pn = [word for word,pos in tagged_sent if pos == 'NNP']
          pn = [x.lower() for x in pn]
          prn=list(set(pn))
          prn= pd.DataFrame({'b_words':prn,'bucket_name':'proper noun'})
          return prn
      df=proper_nouns()
      

      这里的演讲将是你的文字!

      【讨论】:

        猜你喜欢
        • 2016-06-29
        • 1970-01-01
        • 2013-11-21
        • 1970-01-01
        • 2020-01-05
        • 2016-04-24
        • 2012-12-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多