使用 Python 读写固定格式 (MODFLOW) 文本文件
Read and write fixed format (MODFLOW) text files with Python
我正在尝试使用 python 读取、操作和写入文本文件。这些文件包含数字矩阵,由名为 MODFLOW 的 FORTRAN 地下水流代码生成,并且具有不寻常的形状,因为矩阵行被分成几行文件,因此每行不超过 7 个值。因此,具有 37 列的矩阵行输出为 5 行 7 个值 (fmt='%14.6E'),后跟 1 行具有 2 个值。下一个矩阵行然后在新行开始。
我正在尝试读取两个这样的文件,每个文件都有 730 个时间步 x 49 行 x 37 列(大约 18 Mb)。然后我想将数据按元素相乘并将结果写入具有相同格式的新文件。
我可以使用 csv.reader 然后 numpy.savetext 逐行完成,但它非常慢。我怎样才能用更快的 numpy (或类似的)来做到这一点?谢谢!
更新:
我快完成了,只需要去掉输出文件中的逗号即可。显然,目前 pandas 无法做到这一点,因此我可能不得不单独执行此操作。
已解决:
获取 pandas 文本输出并使用 replace() 去除分隔符。还是快。
import pandas as pd
root = 'Taupo'
rctrans = read_csv(root+'._rctrans', header=None, delim_whitespace=True)
rcmult = read_csv(root+'._rcmult', header=None, delim_whitespace=True)
# duplicate rcmult nsteps times to make it the same size as rctrans
nsteps = len(rctrans.index)/len(rcmult.index)
rcmult = pd.concat([rcmult]*nsteps, ignore_index=True)
# multiply the arrays
rctrans = pd.DataFrame(rctrans.values*rcmult.values, columns=rctrans.columns, index=rctrans.index)
# write as csv with no delimiter
with open(root+'._rc','w') as w:
w.write(rctrans.to_csv(header=False, index=False, float_format='%14.6E').replace(',',''))
我认为任何基于 Python 的逐行处理文件的文件 reader 都将具有相似的速度。 Pandas 据说有更快的 CSV reader,但我不熟悉它。你知道你的代码哪里慢了吗?阅读文件?解析?在 list/array?
中收集值
首先,我会尝试编写一个包含 6 行的 reader,将它们拼接在一起以在一行中获得 37 个数字。然后解析它并转换为 37 个浮点数的列表。最后将其附加到主列表。
完成其中 49 个后,创建一个 (49,37) 数组,然后将其保存或附加到另一个包含所有时间步长的列表。
正如关于 np.genfromtxt
或 np.loadtxt
的其他 SO 问题所述,它们接受任何迭代器(或生成器)。所以函数的输入可以是这个聚合器,它将 6 行变成一行 37 列。
在不了解您当前方法的更多细节的情况下,我不能说我的建议是否更快。而且没有类似的测试文件,我真的无法测试替代品。所以在某一层面上,这都是推测性的。
我正在尝试使用 python 读取、操作和写入文本文件。这些文件包含数字矩阵,由名为 MODFLOW 的 FORTRAN 地下水流代码生成,并且具有不寻常的形状,因为矩阵行被分成几行文件,因此每行不超过 7 个值。因此,具有 37 列的矩阵行输出为 5 行 7 个值 (fmt='%14.6E'),后跟 1 行具有 2 个值。下一个矩阵行然后在新行开始。
我正在尝试读取两个这样的文件,每个文件都有 730 个时间步 x 49 行 x 37 列(大约 18 Mb)。然后我想将数据按元素相乘并将结果写入具有相同格式的新文件。
我可以使用 csv.reader 然后 numpy.savetext 逐行完成,但它非常慢。我怎样才能用更快的 numpy (或类似的)来做到这一点?谢谢!
更新:
我快完成了,只需要去掉输出文件中的逗号即可。显然,目前 pandas 无法做到这一点,因此我可能不得不单独执行此操作。
已解决:
获取 pandas 文本输出并使用 replace() 去除分隔符。还是快。
import pandas as pd
root = 'Taupo'
rctrans = read_csv(root+'._rctrans', header=None, delim_whitespace=True)
rcmult = read_csv(root+'._rcmult', header=None, delim_whitespace=True)
# duplicate rcmult nsteps times to make it the same size as rctrans
nsteps = len(rctrans.index)/len(rcmult.index)
rcmult = pd.concat([rcmult]*nsteps, ignore_index=True)
# multiply the arrays
rctrans = pd.DataFrame(rctrans.values*rcmult.values, columns=rctrans.columns, index=rctrans.index)
# write as csv with no delimiter
with open(root+'._rc','w') as w:
w.write(rctrans.to_csv(header=False, index=False, float_format='%14.6E').replace(',',''))
我认为任何基于 Python 的逐行处理文件的文件 reader 都将具有相似的速度。 Pandas 据说有更快的 CSV reader,但我不熟悉它。你知道你的代码哪里慢了吗?阅读文件?解析?在 list/array?
中收集值首先,我会尝试编写一个包含 6 行的 reader,将它们拼接在一起以在一行中获得 37 个数字。然后解析它并转换为 37 个浮点数的列表。最后将其附加到主列表。
完成其中 49 个后,创建一个 (49,37) 数组,然后将其保存或附加到另一个包含所有时间步长的列表。
正如关于 np.genfromtxt
或 np.loadtxt
的其他 SO 问题所述,它们接受任何迭代器(或生成器)。所以函数的输入可以是这个聚合器,它将 6 行变成一行 37 列。
在不了解您当前方法的更多细节的情况下,我不能说我的建议是否更快。而且没有类似的测试文件,我真的无法测试替代品。所以在某一层面上,这都是推测性的。