Python文本处理:NLTK和pandas

10

我正在寻找一种有效的方法在Python中构建一个术语文档矩阵,可以与额外的数据一起使用。

我有一些文本数据和一些其他属性。我想对文本进行一些分析,并希望能够将从文本中提取的特征(如单词标记或LDA主题)与其他属性相关联。

我的计划是将数据加载为Pandas数据框架,然后每个响应将表示一个文档。不幸的是,我遇到了一个问题:

import pandas as pd
import nltk

pd.options.display.max_colwidth = 10000

txt_data = pd.read_csv("data_file.csv",sep="|")
txt = str(txt_data.comment)
len(txt)
Out[7]: 71581 

txt = nltk.word_tokenize(txt)
txt = nltk.Text(txt)
txt.count("the")
Out[10]: 45

txt_lines = []
f = open("txt_lines_only.txt")
for line in f:
    txt_lines.append(line)

txt = str(txt_lines)
len(txt)
Out[14]: 1668813

txt = nltk.word_tokenize(txt)
txt = nltk.Text(txt)
txt.count("the")
Out[17]: 10086
注意,在两种情况下,文本都被处理成只剩下除了空格、字母和,.?!以外的内容(为简单起见)。
如您所见,将pandas字段转换为字符串会返回较少的匹配项,而字符串的长度也较短。
有没有办法改进上面的代码?
此外,str(x)将注释创建为1个大字符串而[str(x) for x in txt_data.comment]创建了一个列表对象,该对象无法分解为词袋。如何最好地生成一个nltk.Text对象,使其保留文档索引?换句话说,我正在寻找一种从tm包中创建Term Document Matrix(即R的等价于TermDocumentMatrix())的方法。
非常感谢。

1
不确定你的问题是什么,但是还有其他的自然语言处理库可能对你有帮助,比如pattern、textblob、C&C。如果你遇到了瓶颈,也可以尝试这些库,它们各自都有自己的优点。 - mid
谢谢@mid,我知道gensim,但之前从未听说过textblob,不过它看起来确实很有用!我对Python还比较新(通常使用R),我真的怀疑我已经在NLTK中遇到了死路,考虑到这个包的流行程度,我肯定是漏掉了什么。 - IVR
1个回答

12

使用 pandasDataFrame 的好处就是可以将 nltk 功能应用于每个 row,例如:

word_file = "/usr/share/dict/words"
words = open(word_file).read().splitlines()[10:50]
random_word_list = [[' '.join(np.random.choice(words, size=1000, replace=True))] for i in range(50)]

df = pd.DataFrame(random_word_list, columns=['text'])
df.head()

                                                text
0  Aaru Aaronic abandonable abandonedly abaction ...
1  abampere abampere abacus aback abalone abactor...
2  abaisance abalienate abandonedly abaff abacina...
3  Ababdeh abalone abac abaiser abandonable abact...
4  abandonable abandon aba abaiser abaft Abama ab...

len(df)

50

txt = df.text.apply(word_tokenize)
txt.head()

0    [Aaru, Aaronic, abandonable, abandonedly, abac...
1    [abampere, abampere, abacus, aback, abalone, a...
2    [abaisance, abalienate, abandonedly, abaff, ab...
3    [Ababdeh, abalone, abac, abaiser, abandonable,...
4    [abandonable, abandon, aba, abaiser, abaft, Ab...

txt.apply(len)

0     1000
1     1000
2     1000
3     1000
4     1000
....
44    1000
45    1000
46    1000
47    1000
48    1000
49    1000
Name: text, dtype: int64

因此,您可以获得每个row条目的.count():

txt = txt.apply(lambda x: nltk.Text(x).count('abac'))
txt.head()

0    27
1    24
2    17
3    25
4    32

您可以使用以下方式对结果进行求和:

txt.sum()

1239

谢谢@Stefan,这几乎解决了我的问题,但是txt对象仍然是一个pandas数据框对象,这意味着我只能使用一些NLTK函数,如applymapfor循环。但是,如果我想做像nltk.Text(txt).concordance("the")这样的事情,我会遇到问题。为了解决这个问题,我仍然需要将整个文本变量转换为字符串,正如我们在我的第一个例子中看到的那样,该字符串将因某种原因被截断。有没有什么想法可以克服这个问题?非常感谢! - IVR
1
你可以使用以下代码将整个 text 列转换为一个单词列表:[t for t in df.text.tolist()] - 可以在创建后或 .tokenize() 后进行。 - Stefan

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