【问题标题】:From a large text file to a sparse matrix with Python使用 Python 从大文本文件到稀疏矩阵
【发布时间】:2014-04-03 23:36:17
【问题描述】:

我正在尝试找到一种有效的方法来读取一个非常大的文本文件(大约 2,000,000 行)。这些行中大约 90%(实际上是最后 90%)具有三列格式,用于存储稀疏矩阵。

这就是我所做的。首先,我处理文件的前 10%:

i=1
cpt=0
skip=0
finnum=0
indice=1 
vec=[]
mat=[]
for line in fileinput.input("MY_TEXT_FILE.TXT"):
if i==1:
    # skipping the first line
    skip = 1
if (finnum == 0)and(skip==0):
    # special reading operation for the first 10% (approximately)
    tline=shlex.split(line)
    ind_loc=0
    while ind_loc<len(tline):
    if (int(tline[ind_loc])!=0):
            vec.append(int(tline[ind_loc]))
        ind_loc=ind_loc+1   
if (finnum == 1)and(skip==0):
    print('finnum = 1')
    h=input()    
        break       
    if (' 0' in line):
    finnum = 1
if skip == 0:
    i=i+1
else:
    skip=0
    i=i+1
cpt=cpt+1

然后我将剩下的 90% 提取到一个列表中:

matrix=[]
with open('MY_TEXT_FILE.TXT') as f:
for i in range(cpt):
    f.next()
for line in f:
    matrix.append(line)

这允许以低内存消耗非常快速地读取文本文件。缺点是 ma​​trix 是一个字符串列表,每个字符串类似于:

>>> matrix[23]
'           5          11  8.320234929063493E-008\n'

我尝试在 ma​​trix 的行上使用迭代过程并结合 shlex.split 命令从字符串列表转到数组,但这是非常耗时。

您是否知道从字符串列表到数组的快速策略?

我想知道是否有比这个过程更快的方法:

A=[0]*len(matrix)
B=[0]*len(matrix)
C=[0]*len(matrix)
for i in range(len(matrix)):
     line = shlex.split(matrix[i])
     A[i]=float(line[0])
     B[i]=float(line[1])
     C[i]=float(line[2])

阿兰

【问题讨论】:

  • "从字符串列表到数组" 你到底想做什么?您想在内存中保存矩阵(= 列表列表)吗?
  • 我希望能够访问我列表中的每个数值并获得关联的 (nx3) 矩阵。
  • 你能以某种方式修改文件的格式吗?因为听起来 HDF5 非常适合。
  • 我不能完全访问文件的格式,它是由一个我无法控制的外部例程提供的......
  • 你能计算出阅读一百万行这些行需要多长时间吗?只是为了了解更多

标签: python text sparse-matrix


【解决方案1】:

看,我想出了这个混合解决方案,它似乎工作得更快。我创建了一个 100 万个样本随机数据,就像你上面提到的那样,并对你的代码进行了计时。顺便说一句,我的 Mac 电脑用了 77 秒,这是一台超级快的电脑。 使用 numpy 而不是 shlex 来拆分字符串最终需要 5 秒的处理过程。

A=[0]*len(matrix)
B=[0]*len(matrix)
C=[0]*len(matrix)
for i in range(len(matrix)):
    full_array = np.fromstring(matrix[i], dtype=float, sep=" ")
    A[i]=full_array[0]
    B[i]=full_array[1]
    C[i]=full_array[2]

我进行了几次测试,它似乎运行良好,速度提高了 14 倍。 希望对你有帮助。

【讨论】:

  • 太棒了!确实更快,似乎工作得很好。谢谢!
  • 我猜这个问题可能是由于这个库的目标而导致的 shlex,它确实很好但不是为了这个目标。
【解决方案2】:

当您处理大量数值数据时,您应该真正使用Numpy,而不是纯python。这通常会快 10 倍以上,并且可以让您访问 Matlab 风格的复杂计算。我现在没有时间转换您的代码(并且拥有一个示例文件是最简单的),但可以肯定的是,使用numpy.loadtxt 可以快速有效地读取文件的第二部分。跳过第一部分并转换为浮点数的代码的整个第二部分可能可以通过以下方式完成:

A, B, C = np.loadtxt('MY_TEXT_FILE.TXT', skiprows = cpt, unpack = True)

您可能想使用数据格式(通过添加dtype = (int, int, float) 左右,不知道具体如何执行此操作),因为我猜前两列是整数。

另请注意,numpy 有一个可用的 sparse matrix 数据类型。

【讨论】:

  • 感谢您的提议。然而,这意味着 RAM 内存的大量消耗(类似于 Matlab 中的 importdata 函数)。我试图避免这种情况。不过速度更快。
  • 内存消耗对您来说是个大问题吗?因为我想不出比这更快的事情了
  • 内存消耗实际上是我尝试使用Python进行这个读取操作的原因。 Matlab 中的 importdata 命令有时可能需要太多 RAM。当前的解决方案并不是特别慢,但我想确保没有明显的改进是我遗漏的。谢谢!
  • 我假设在后台,loadtxt 一次只读取一行文本,然后将其直接转换为浮点数,因此您只需要 A、B 和 C 数组的空间。在任何现代计算机上,几百万个项目的数组都不应该成为问题。如果文件更大,您应该考虑一次以 100.000 行为单位读取文件。也许您需要像 numpy.fromfile 或 numpy.genfromtxt 这样的变体,因为 loadtxt 似乎不处理文件指针并且没有限制您读取的数据量的选项。但很可能你不需要这个。
猜你喜欢
  • 2014-08-17
  • 2013-11-05
  • 2022-08-18
  • 2016-07-02
  • 2012-09-04
  • 2017-04-21
  • 1970-01-01
  • 2014-07-14
  • 1970-01-01
相关资源
最近更新 更多