【问题标题】:speed-up python function to process files with data segments separated by a blank space加速python函数来处理数据段由空格分隔的文件
【发布时间】:2010-02-22 14:17:55
【问题描述】:

我需要处理数据段用空格隔开的文件,例如:

93.18 15.21 36.69 33.85 16.41 16.81 29.17 
21.69 23.71 26.38 63.70 66.69 0.89 39.91 
86.55 56.34 57.80 98.38 0.24 17.19 75.46 
[...]
1.30 73.02 56.79 39.28 96.39 18.77 55.03

99.95 28.88 90.90 26.70 62.37 86.58 65.05 
25.16 32.61 17.47 4.23 34.82 26.63 57.24 
36.72 83.30 97.29 73.31 31.79 80.03 25.71 
[...]
2.74 75.92 40.19 54.57 87.41 75.59 22.79

.
.
.

为此,我正在使用以下功能。 在每次调用中,我都会获得必要的数据,但我需要加快代码速度。

有没有更有效的方法?

编辑我将更新代码以实现改进

原文:

def get_pos_nextvalues(pos_file, indices):
    result = []
    for line in pos_file:
        line = line.strip()
        if not line:
            break
        values = [float(value) for value in line.split()]
        result.append([float(values[i]) for i in indices])
    return np.array(result)

新:

def get_pos_nextvalues(pos_file, indices):
    result = ''
    for line in pos_file:
        if len(line) > 1:
            s = line.split()
            result += ' '.join([s [i] for i in indices])
        else:
            break
    else:
        return np.array([])
    result = np.fromstring(result, dtype=float, sep=' ')
    result = result.reshape(result.size/len(indices), len(indices))
    return result

.

pos_file = open(filename, 'r', buffering=1024*10)

[...]

while(some_condition):
    vs = get_pos_nextvalues(pos_file, (4,5,6))
    [...]

加速 = 2.36

【问题讨论】:

    标签: python numpy performance


    【解决方案1】:

    不将浮点数转换为浮点数将是第一步。不过,我建议先profile your code,然后尝试优化瓶颈部分。

    我了解到您已经更改了原始代码,但是

    values = [value for value in line.split()]
    

    也不是什么好事。如果这就是你的意思,就写values = line.split()

    看看你是如何使用 NumPy 的,我建议你使用methods of file reading that are demonstrated in their docs

    【讨论】:

      【解决方案2】:

      您只读取每个字符一次,因此没有任何实际性能可提高。

      如果空行包含大量空格,您可以合并剥离和拆分。

      您还可以节省一些时间从一开始就初始化 numpy 数组,而不是先创建一个 python 数组然后再进行转换。

      【讨论】:

      • 更改 «line = line.strip(); if not line:» for «if len(line)
      【解决方案3】:

      尝试增加读取缓冲区,IO 可能是你代码的瓶颈

      open('file.txt', 'r', 1024 * 10) 
      

      如果数据是完全连续的,您可以尝试逐行跳过代码并一次转换一堆行

      【讨论】:

        【解决方案4】:

        而不是:

        if len(line) <= 1: # only '\n' in «empty» lines
            break
        values = line.split()
        

        试试这个:

        values = line.split()
        if not values: # line is wholly whitespace, end of segment
            break
        

        【讨论】:

          【解决方案5】:

          numpy.fromfile 不适合你?

          arr = fromfile('tmp.txt', sep=' ', dtype=int)
          

          【讨论】:

          • 我正在寻找一种有效的方法来读取每个数据段到 str 并使用 numpy.fromstring
          【解决方案6】:

          这是一个可能对于少数索引更快的变体。它只构建一个包含所需值的字符串,这样np.fromstring 的工作就更少了。

          def get_pos_nextvalues_fewindices(pos_file, indices):
              result = ''
              for line in pos_file:
                  if len(line) > 1:
                      s = line.split()
                      for i in indices:
                          result += s[i] + ' '
                  else:
                      return np.array([])
              result = np.fromstring(result, dtype=float, sep=' ')
              result = result.reshape(result.size/len(indeces), len(indeces))
              return result
          

          这权衡了split() 的开销和增加的循环以减少解析。或者您可以采取一些巧妙的正则表达式技巧来直接提取所需的子字符串?

          旧答案

          np.mat('1.23 2.34 3.45 6\n1.32 2.43 7 3.54') 将字符串转换为 numpy 浮点值矩阵。这可能是一个更快的内核供您使用。例如:

          import numpy as np
          def ReadFileChunk(pos_file):
              chunktxt = ""
              for line in pos_file:
                  if len(line) > 1:
                      chunktxt = chunktxt + line
                  else:
                      break
          
              return np.mat(chunktxt).tolist()
              # or alternatively
              #return np.array(np.mat(s))
          

          然后您可以将索引内容移至另一个函数。希望numpy 在内部解析字符串比重复调用float() 更快。

          【讨论】:

          • 我正在尝试这样的事情,但正在寻找一种更有效的方式来读取数据块,逐行连接。我使用 np.fromstring 而不是 np.mat,我需要一个数组并进行重塑并不昂贵。但是让 numpy 解析字符串这绝对是一个实质性的改进。
          • return np.array(np.mat(s)) 比使用 no.fromstring 更昂贵
          • 所以 np.fromstring + reshape 比 np.array(np.mat(s)) 快吗?呃,好吧。我学到了一些新东西,至少,我认为 np.fromstring 是用于打包成字符串的二进制数据。
          • 新答案以类似的速度运行,但我更喜欢它,因为让我不必担心将来会改变行大小(现在是 7 个)
          • upss... 我再次为这个答案投了票,但 stackoverflot 投了 0 并且不让我再次投票:(。我需要深入阅读常见问题解答。
          猜你喜欢
          • 1970-01-01
          • 2013-12-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-05-19
          • 1970-01-01
          相关资源
          最近更新 更多