【问题标题】:Reading large formatted text file with NumPy使用 NumPy 读取大格式文本文件
【发布时间】:2013-02-19 22:29:33
【问题描述】:

我自愿帮助某人将有限元网格从一种格式转换为另一种格式(i-deas *.unv 到 Alberta)。我已经使用 NumPy 对网格进行了一些额外的整形,但是在将原始文本文件数据读取到 NumPy 数组中时遇到了问题。到目前为止,我已经尝试过 genfromtxt 和 loadtxt 没有成功。

一些细节:

1) 所有组都由单独的行上的页眉和页脚标志“-1”分隔。

2) NODE 组在其自己的行上有一个标题“2411”。我只想从该组中读取交替行,跳过每行 4 个整数,但读取带有 3 个 Fortran 双精度数字的行。

3) ELEMENT 连接组在其自己的行上有一个标题“2412”。所有数据都是整数,只需要读取前 4 列。由于缺少 2 和 3 节点元素的值,NumPy 数组中会有一些空槽。

4) “2477”节点组我想我可以使用正则表达式来查找要读取的行。

5) 真实数据文件将包含大约 100 万行文本,因此我非常希望尽可能将其矢量化(或者 NumPy 为快速读取内容所做的任何事情)。

对不起,如果我提供了太多信息,谢谢。

以下几行是 *.unv 文本文件格式的部分示例。

    -1
  2411
  146303         1         1        11
  6.9849462399269246D-001  8.0008842847097805D-002  6.6360238055630028D-001
  146304         1         1        11
  4.1854795755893875D-001  9.1256034628308313D-001  3.5725496189239300D-002
  146305         1         1        11
  7.5541258490349616D-001  3.7870257739063029D-001  2.0504544370783115D-001
  146306         1         1        11
  2.7637569971086767D-001  9.2829777518336010D-001  1.3757239038663285D-001
   -1
   -1
 2412
     9        21         1         0         7         2
     0         0         0
     1         9
    10        21         1         0         7         2
     0         0         0
     9        10
  1550        91         6         0         7         3
   761      3685      2027
  1551        91         6         0         7         3
   761      2380      2067
 39720       111         1         0         7         4
 71854     59536     40323     73014
 39721       111         1         0         7         4
 45520     48908    133818    145014
   -1
   -1
   2477
     1         0         0         0         0         0         0      3022
PERMANENT GROUP1
     7         2         0         0         7         3         0         0
     7         8         0         0         7         7         0         0
     7       147         0         0         7       148         0         0
     2         0         0         0         0         0         0      2915
PERMANENT GROUP2
     7         1         0         0         7         5         0         0
     7         4         0         0         7         6         0         0
     7         9         0         0         7        11         0         0
   -1

【问题讨论】:

    标签: numpy python-2.7


    【解决方案1】:

    numpy 方法 genfromtxtloadtxt 很难应用于整个文件,因为您的数据具有非常特殊的结构(根据您所在的节点而变化)。因此,我建议以下策略:

    • 逐行读取文件,通过分析判断你在哪个节点。

    • 如果您在一个只有少量数据的节点中(例如,您必须交替读取行,因此无法连续读取),请逐行读取并处理行。

    • 当你到达一个有大量数据的部分(比如有“真实数据”的部分),使用 numpys fromfile 方法读取数据,如下所示:

      mydata = np.fromfile(fp, sep=" ", dtype=int, count=number_of_elements)
      mydata.shape = (100000, 3)    # Reshape it to the desired shape as fromfile
                                    # returns a 1D array.
      

    这样,您可以将逐行处理的灵活性与快速读取和转换大量数据的能力相结合。

    更新:重点是,你打开文件,逐行读取,当你到达一个有大量数据的地方时,你将文件描述符传递给 fromfile。

    下面是一个简化的例子:

    import numpy as np
    
    fp = open("test.dat", "r")
    line = fp.readline()
    ndata = int(line.strip())
    data = np.fromfile(fp, count=ndata, sep=" ", dtype=int)
    fp.close()
    

    这将从文件test.dat 中读取数据,其内容如下:

    10
    1 2 3 4 5
    6 7 8 9 10
    

    使用fp.read() 显式读取第一行,处理(确定要读取的整数数量),然后np.fromfile() 读取适当的数据块并将其存储在一维数组data中。

    UPDATE2:或者,您可以将整个文本读入缓冲区,然后确定大块数据的开始和结束位置,并直接通过np.fromstring 进行转换:

    fp = open("test.dat", "r")
    txt = fp.read()
    fp.close()
    # Now determine starting and end positions (startpos, endpos)
    # ..
    # pass text that portion of the text to the fromstring function.
    data = np.fromstring(txt[startpos:endpos], dtype=int, sep=" ")
    

    或者,如果很容易形成一个正则表达式,您可以直接在文件上使用fromregex()

    【讨论】:

    • 感谢您的建议。查看“fromfile”命令,它似乎是从第一行读取文件,因此不允许仅读取特定块。我查看了使用“open”命令为上面的“fp”定义一个块,但这似乎也只能从第一行读取文件。
    • 我在上面添加了一个简化的例子。
    • 感谢您的详细说明!我缺少的一点是 readline() 命令具有告诉 fromfile 命令它应该从当前行而不是文件开头读取 fp 的效果。有没有办法将起始行设置为某个值而不必多次调用 readline() ?我可以通过在行首搜索字符串“-1”来快速找到数据块开头和结尾的行号,但必须在循环中调用 readline() 才能到达所需的起点放慢速度。谢谢!
    • 我再次扩展了答案。 :-)
    猜你喜欢
    • 2013-08-19
    • 2022-11-12
    • 1970-01-01
    • 2012-11-25
    • 2014-03-09
    • 1970-01-01
    • 1970-01-01
    • 2016-01-07
    • 1970-01-01
    相关资源
    最近更新 更多