用pandas和numpy解析冒号分隔的稀疏数据
我想用pandas或numpy来解析一种数据文件,这种文件的格式是“列索引:值”。比如说:
0:23 3:41
1:31 2:65
这对应的矩阵是:
[[23 0 0 41]
[0 31 65 0]]
这种方式在文件中表示稀疏数据似乎很常见,但我找不到一种简单的方法来解析它,而不需要在调用read_csv之后进行某种迭代处理。
2 个回答
1
那么,逐行解析文件是否可行,比如:
from scipy.sparse import coo_matrix
rows, cols, values = [], [], []
with open('sparse.txt') as f:
for i, line in enumerate(f):
for cell in line.strip().split(' '):
col, value = cell.split(':')
rows.append(i)
cols.append(int(col))
values.append(int(value))
matrix = coo_matrix((values, (rows, cols)))
print matrix.todense()
还是说你需要一个更快的一步实现?我不太确定这是否可能。
编辑 #1: 你可以通过使用正则表达式来避免逐行分割的过程,这样可以得到以下替代实现:
import numpy as np
from scipy.sparse import coo_matrix
import re
rows, cols, values = [], [], []
with open('sparse.txt') as f:
for i, line in enumerate(f):
numbers = map(int, re.split(':| ', line))
rows.append([i] * (len(numbers) / 2))
cols.append(numbers[::2])
values.append(numbers[1::2])
matrix = coo_matrix((np.array(values).flatten(),
(np.array(rows).flatten(),
np.array(cols).flatten())))
print matrix.todense()
编辑 #2: 我找到了一种更简短的解决方案,没有显式的循环:
from scipy.sparse import coo_matrix, vstack
def parseLine(line):
nums = map(int, line.split(' '))
return coo_matrix((nums[1::2], ([0] * len(nums[0::2]), nums[0::2])), (1, 4))
with open('sparse.txt') as f:
lines = f.read().replace(':', ' ').split('\n')
cols = max(map(int, " ".join(lines).split(" "))[::2])
M = vstack(map(parseLine, lines))
print M.todense()
这个循环隐藏在对 lines
的 map
命令中。我认为没有完全不使用循环的解决方案,因为大多数内置函数都需要用到循环,而且很多字符串解析的方法,比如 re.finditer
只会返回迭代器。
2
我最近发现,这实际上是svm-light格式的数据集。你可以使用一个叫做svm加载器的工具来读取这样的数据集,具体可以参考这个链接:
http://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_svmlight_file.html