繁体   English   中英

从 Pandas DataFrame 计算 TF-IDF(没有 sklearn)

[英]Calculating TF-IDF from a Pandas DataFrame (without sklearn)

所以我有一个 Pandas DataFrame:这里

正如您所看到的,我已将其标记为使其更清晰(书名只是书名,数字是它们各自的频率)。

要计算 TF-IDF,我必须实现一个名为“choice”的 function,其签名如下:

def choice(term, documents):

其中“term”是 dataframe 中存在的任何有效词,“documents”是 pandas dataframe 本身。 function 计算 dataframe 中所有书籍的 TF-IDF(因此,行,因为每本书都是一个新行),然后返回具有最高 TF-IDF 值的书籍的名称,例如:

choice('the', mydataframe)

# output: pg16238.txt

我遇到的问题是我无法从 dataframe 中提取特定频率,因为已将索引从标准编号(0、1、2 等)重命名为书名,如您在呈现内置的“.str.contains”function 不知何故无用(它不起作用)。

我搜索了很多,发现它以某种方式变成了“多索引”dataframe? (我是初学者,所以我不知道如何解决这个问题)。

我遇到的另一个问题是计算完成后我不知道如何返回书名。 就像,我是否应该列出索引,然后创建一个看起来像这样的字典:

{'book-title': tf-idf-value}

然后返回最高值? 请帮助我找出解决此问题的适当方法。

我已经成功编写了一个有效的 IDF 计算 function:

def get_IDF(self, term):
    N = 0
    D = len(self.files_list)
    for file in self.files_list:
        with open(file, 'r', encoding='utf-8-sig', errors='replace') as f:
            temp_cleaned_data = ''.join(i.lower() for i in f.read() if ord(i) < 128).translate(str.maketrans('', '', string.punctuation)).replace('\n', ' ')
            if self.contains_word(temp_cleaned_data, term):
                N += 1
    return 1 + (math.log(D / (1 + N)))

“files_list”是存储在当前目录中的文件列表。

另外,请原谅我糟糕的编码“temp_cleaned_data”,我稍后会对其进行重构,对此感到抱歉。 (我知道使用“.isalnum()”确实有更简单的方法可以做到这一点,但我也在尝试学习一些列表理解和函数式编程,所以我尝试了不同的东西并将它们拼凑在一起,看看它是如何工作的)。

无论如何,我真的很感激任何形式的帮助来解决这个问题,谢谢。 TF-IDF 的公式为:

术语频率(术语)x idf(术语)

注意:我提供的 DataFrame 屏幕截图只是完整 dataframe 的一部分。 此外,书名可能会有所不同,书籍的数量不仅是6本,而且可以是N本。 因此,我打算对 function 进行编码,它可以考虑上述条件。

编辑:如果我们使用 Pandas,我们可以创建 lambda function -

choice = lambda term, documents: documents[documents[term] == documents[term].max()].index[0]

输入:

choice('accept', documents=df)

Output:

'1661-0.txt'

***对于想要重新创建(上半部分)此示例的任何人:

import pandas as pd
index = ['11-0.txt','1342-0.txt','1661-0.txt','1952-0.txt','84-0.txt','pg16328.txt',]
cols = ['accept','acceptance','accepted','accepting','access','accessed']

df = pd.DataFrame(index=index, columns=cols)

### Un-comment to print formatted pairs
#for i in index:
    #for j in cols:
        #print(f'df.loc[\'{i}\', \'{j}\'] = ')

df.loc['11-0.txt', 'accept'] = 0.000034
df.loc['11-0.txt', 'acceptance'] = 0.000034
df.loc['11-0.txt', 'accepted'] = 0.000067
df.loc['11-0.txt', 'accepting'] = 0.000034
df.loc['11-0.txt', 'access'] = 0.000336
df.loc['11-0.txt', 'accessed'] = 0.000034
df.loc['1342-0.txt', 'accept'] = 0.000051
df.loc['1342-0.txt', 'acceptance'] = 0.000013
df.loc['1342-0.txt', 'accepted'] = 0.000026
df.loc['1342-0.txt', 'accepting'] = 0.000013
df.loc['1342-0.txt', 'access'] = 0.000153
df.loc['1342-0.txt', 'accessed'] = 0.000013
df.loc['1661-0.txt', 'accept']= 0.000144
df.loc['1661-0.txt', 'acceptance'] = 0.000032
df.loc['1661-0.txt', 'accepted'] =0.000144
df.loc['1661-0.txt', 'accepting'] = 0.000040
df.loc['1661-0.txt', 'access'] = 0.000080
df.loc['1661-0.txt', 'accessed'] = 0.000008
df.loc['1952-0.txt', 'accept'] = 0.000046
df.loc['1952-0.txt', 'acceptance'] = 0.000009
df.loc['1952-0.txt', 'accepted'] = 0.000037
df.loc['1952-0.txt', 'accepting'] = 0.000009
df.loc['1952-0.txt', 'access'] = 0.000092
df.loc['1952-0.txt', 'accessed'] = 0.000009
df.loc['84-0.txt', 'accept'] = 0.000109
df.loc['84-0.txt', 'accepted'] = 0.000218
df.loc['84-0.txt', 'accepting'] =0.000109
df.loc['84-0.txt', 'access'] = 0.001089
df.loc['84-0.txt', 'accessed'] = 0.000109
df.loc['pg16328.txt', 'accept'] = 0.000045
df.loc['pg16328.txt', 'accepted'] = 0.000361
df.loc['pg16328.txt', 'accepting'] =0.000090
df.loc['pg16328.txt', 'access'] = 0.000293
df.loc['pg16328.txt', 'accessed'] = 0.000023

我对您的实现做了一些修改,我假设您已经计算了 IDF DataFrame。 让我们创建一个虚拟的一些统一值:

IDF = pd.DataFrame([1.0/len(df.index)]*len(df.index), index = df.index)
print(IDF)


                0
11-0.txt     0.166667
1342-0.txt   0.166667
1661-0.txt   0.166667
1952-0.txt   0.166667
84-0.txt     0.166667
pg16328.txt  0.166667

我还将您的df名称更改为TF

TF = df.copy()



def choice(term, TF, impute_val=0.000001):
    TF = TF.fillna(impute_val)

    # Based on the formula provided, calculate the TFIDF score for all documents of this term
    tfidf_score = TF[term].values.ravel() * IDF.values.ravel()

    doc_names = TF.index.tolist()
    # sort by TFIDF score and return the doc name that has max tfidf value
    return sorted(zip(doc_names,tfidf_score),key=lambda x: x[1])[-1][0]

print(choice(term='accept', TF=TF))

'1661-0.txt'

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM