Python 2.7:用字典制作一个tf:idf脚本

时间:2014-08-27 13:57:56

标签: python tf-idf

我想编写一个使用字典来获取tf:idf(比例?)的脚本。

我们的想法是让脚本使用os.walk查找目录及其子目录中的所有.txt文件:

files = []
for root, dirnames, filenames in os.walk(directory):
    for filename in fnmatch.filter(filenames, '*.txt'):
        files.append(os.path.join(root, filename))

然后使用该列表查找所有单词以及它们出现的次数:

def word_sort(filename3):
    with open(filename3) as f3:
        passage = f3.read()
    stop_words = "THE OF A TO AND IS IN YOU THAT IT THIS YOUR AS AN BUT FOR".split()
    words = re.findall(r'\w+', passage)
    cap_words = [word.upper() for word in words if word.upper() not in stop_words]
    word_sort = Counter(cap_words)
    return word_sort

term_freq_per_file = {}
for file in files:
    term_freq_per_file[file] = (word_sort(file))

最终会出现如下字典:

 '/home/seb/Learning/ex15_sample.txt': Counter({'LOTS': 2, 'STUFF': 2, 'HAVE': 1,
                                     'I': 1, 'TYPED': 1, 'INTO': 1, 'HERE': 1,
                                      'FILE': 1, 'FUN': 1, 'COOL': 1,'REALLY': 1}),

在我看来,这给了我每个文件的单词频率。

如何找到实际的tf?

我怎么能找到idf?

我指的是术语频率,它是一个单词(术语)出现在文档中的次数

TF(t)=(术语t出现在文档中的次数)/(文档中的术语总数)。

而idf我的意思是逆文档频率,其中文档频率是单词出现的文档数量

IDF(t)= log_e(文件总数/含有期限t的文件数量)。

为了澄清,我的问题是如何提取这些值并将它们放入公式中,我知道它们在那里,但我不知道如何撤回它们并进一步使用它们。


我决定制作另一个字典,其中包含使用该字的文件,如下所示:

{word : (file1, file2, file3)}

通过这样迭代第一个字典:

for file in tfDic:
     word = tfDic[file][Counter]
     for word in tfDic:
        if word not in dfDic.keys():
            dfDic.setdefault(word,[]).append(file)
        if word in dfDic.keys():
            dfDic[word].append(file)

问题在于这一行:

word = tfDic[file][Counter]

我认为它会“导航”到单词,但是我注意到单词是计数器字典中的键,它是tfDic(文件)的值。

我的问题是,如何告诉它迭代单词('Counter'字典的键)?

3 个答案:

答案 0 :(得分:0)

如果您想坚持使用当前的数据结构,则必须深入研究每个单词的每个文件的整个结构,以便计算其idf

# assume the term you are looking for is in the variable term
df = 0
for file in files:
    if term in term_freq_per_file[file]:
        df += 1
idf = math.log(len(files)/df)

此答案的早期版本包含替代数据结构的草图,但这可能已经足够了。

答案 1 :(得分:0)

(最终)

我决定回去改变我的字数公式,以便代替:

word_sort = Counter(cap_words)

我已经遍历列表中的单词,并根据它们出现的次数创建了自己的字典:

word_sort = {}
for term in cap_words:
    word_sort[term] = cap_words.count(term)

所以我不是每次都有一个子字典(Counter),而是以tfDic结束这个:

'/home/seb/Learning/ex17output.txt': {'COOL': 1,
                                   'FILE': 1,
                                   'FUN': 1,
                                   'HAVE': 1,
                                   'HERE': 1,
                                   'I': 1,
                                   'INTO': 1,
                                   'LOTS': 2,
                                   'REALLY': 1,
                                   'STUFF': 2,
                                   'TYPED': 1},

然后我遍历tfDic [file]的键来创建另一个Dictionary,其中包含已使用给定单词的文件中的信息:

for file in tfDic:
word = tfDic[file].keys()
for word in tfDic[file]:
    if word not in dfDic.keys():
        dfDic.setdefault(word,[]).append(file)
    if word in dfDic.keys():
        dfDic[word].append(file)

,最终结果如下:

 'HERE': ['/home/seb/Learning/ex15_sample.txt',
      '/home/seb/Learning/ex15_sample.txt',
      '/home/seb/Learning/ex17output.txt'],

现在我计划提取'价值并将它们放入我之前提到的公式中。

答案 2 :(得分:0)

除非这是关于tf-idf如何运作的学习练习,否则我建议使用内置的scikit-learn类来完成此任务。

首先,为每个文件创建一个计数字典数组。然后将计数字典数组输入DictVectorizer,然后将输出稀疏矩阵输入TfidfTransformer

from sklearn.feature_extraction import DictVectorizer from sklearn.feature_extraction.text import TfidfTransformer dv = DictVectorizer() D = [{'foo': 1, 'bar': 2}, {'foo': 3, 'baz': 1}] X = dv.fit_transform(D) tv = TfidfTransformer() tfidf = tv.fit_transform(X) print(tfidf.to_array())