解析冒号将稀疏数据与pandas和numpy分开

时间:2014-08-04 15:24:12

标签: python numpy pandas scipy

我想用pandas / numpy中的col_index:value格式解析数据文件。例如:

0:23 3:41 1:31 2:65

将对应于此矩阵:

[[23 0 0 41] [0 31 65 0]]

这似乎是在文件中表示稀疏数据的一种非常常见的方式,但是我无法在调用read_csv之后找到一种解析它的简单方法,而无需进行某种迭代。

2 个答案:

答案 0 :(得分:2)

我最近发现这实际上是svm-light格式,您可以使用svm加载器读取这样的数据集,如:

http://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_svmlight_file.html

答案 1 :(得分: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()

循环隐藏在作为map的{​​{1}}命令中。我认为根本没有没有循环的解决方案,因为大多数内置函数都使用它们,而许多字符串解析方法如lines只产生迭代器。