2016-04-01 38 views
2

我正在使用Python尝试使用Okapi BM25 model对文档进行排名。Python熊猫:从空白分隔的'.dat'文件生成文档 - 矩阵

我认为我可以更有效地计算Score(D,Q)所需的某些术语,如IDF(Inverse Document Frequency)(即:计算特定术语(列)的所有非零行)。此外,我可以在矩阵中为实际分数添加一个新列,然后按此排序以对文档进行排序。

文档术语矢量被存储在一个.dat文件,它的结构类似于以下:

D1 7:10 2:5 
D2 1:2 3:4 

其中D1是一个文档ID和7:10表示与ID 7出现的术语10

在目前,我正在使用以下代码将其读入列表清单中:

fname = "dtv.dat" 
f = open(fname, "r") 
l = [x.strip(" \n").split(" ") for x in f.readlines()] 

这将产生以下输出给定的例子:

[['D1', '7:10', '2:5'],['D2' '1:2', '3:4']] 

定列表格式的这份名单中,什么是最有效的方式将其转换为一个Python大熊猫数据框类似以下内容:

0  1  2  3  7 
D1  0  5  0  10  
D2  2  0  4  0 

回答

1

如果每个文档在该文件中只出现一次,您的答案似乎没有问题。否则,代码将覆盖字典d中的一些记录。

我认为有以下会比较一般:

import numpy as np 
import pandas as pd 

fname = 'example.txt' 

full_list = [] 
with open(fname, "r") as f: 
    for line in f: 
     arr = line.strip(" \n").split(" ") 
     for chunk in arr[1:]: 
      # converting numbers to ints: 
      int_pair = [int(x) for x in chunk.split(":")] 
      full_list.append([arr[0], *int_pair]) 

df = pd.DataFrame(full_list) 

df2 = df.pivot_table(values = 2, index = 0, columns = 1, aggfunc = np.sum, fill_value = 0) 

工作原理:

>>> cat 'example.txt' 
D1 1:3 2:2 3:3 
D2 1:4 2:7 
D2 7:1 
D1 2:4 4:2 
D1 4:1 4:3 
>>> full_list 
Out[37]: 
[['D1', 1, 3], 
['D1', 2, 2], 
['D1', 3, 3], 
['D2', 1, 4], 
['D2', 2, 7], 
['D2', 7, 1], 
['D1', 2, 4], 
['D1', 4, 2], 
['D1', 4, 1], 
['D1', 4, 3]] 
>>> df 
Out[38]: 
    0 1 2 
0 D1 1 3 
1 D1 2 2 
2 D1 3 3 
3 D2 1 4 
4 D2 2 7 
5 D2 7 1 
6 D1 2 4 
7 D1 4 2 
8 D1 4 1 
9 D1 4 3 
>>> df2 
Out[39]: 
1 1 2 3 4 7 
0     
D1 3 6 3 6 0 
D2 4 7 0 0 1 
+0

哇,很漂亮的确! – jfive

0

使用将列表更改为列表的列表,将列表转换为字典ID和词典频率字典,然后直接转换为DataFrame来完成此任务,任何改进都非常值得欢迎!

def term_matrix(fname): 
f = open(fname, "r") 
l = [x.strip(" \n").split(" ") for x in f.readlines()] 

d = dict() 

for i in l: 
    d[i[0]] = dict(t.split(":") for t in i[1:]) 

return pd.DataFrame(d).transpose()