Rom*_*lov 8 python numpy input large-files bigdata
我有一大堆用CSV文件编写的数字,只需加载该数组的一部分.从概念上讲,我想调用np.genfromtxt()然后对结果数组进行行切片,但是
MATLAB具有textscan()可以获取文件描述符并只读取文件块的功能.在NumPy中有类似的东西吗?
现在,我定义了以下函数,它只读取满足给定条件的行:
def genfromtxt_cond(fname, cond=(lambda str: True)):
res = []
with open(fname) as file:
for line in file:
if cond(line):
res.append([float(s) for s in line.split()])
return np.array(res, dtype=np.float64)
Run Code Online (Sandbox Code Playgroud)
此解决方案有几个问题:
genfromtxt检测类型,这些类型可能因列而异; 还缺少值,转换器,跳过等;是否存在实现过滤的标准函数,或MATLAB的一些对应函数textscan?
The*_*eke 16
我可以想到两种方法可以提供您要求的一些功能:
要以块/ /或n行/等的步幅读取文件:
您可以传递generator给numpy.genfromtxt以及numpy.loadtxt.这样,您可以高效地从文本文件中加载大型数据集,同时保留两个函数的所有方便的解析功能.
仅从符合可以表示为正则表达式的条件的行读取数据:
您可以使用numpy.fromregex并使用a regular expression来精确定义应加载输入文件中给定行的哪些标记.与模式不匹配的行将被忽略.
为了说明这两种方法,我将使用我的研究背景中的一个例子.
我经常需要加载具有以下结构的文件:
6
generated by VMD
CM 5.420501 3.880814 6.988216
HM1 5.645992 2.839786 7.044024
HM2 5.707437 4.336298 7.926170
HM3 4.279596 4.059821 7.029471
OD1 3.587806 6.069084 8.018103
OD2 4.504519 4.977242 9.709150
6
generated by VMD
CM 5.421396 3.878586 6.989128
HM1 5.639769 2.841884 7.045364
HM2 5.707584 4.343513 7.928119
HM3 4.277448 4.057222 7.022429
OD1 3.588119 6.069086 8.017814
Run Code Online (Sandbox Code Playgroud)
这些文件可能很大(GB),我只对数值数据感兴趣.所有数据块都具有相同的大小 - 6在本例中 - 它们总是由两行分隔.所以stride块是8.
首先,我将定义一个过滤掉不需要的行的生成器:
def filter_lines(f, stride):
for i, line in enumerate(f):
if i%stride and (i-1)%stride:
yield line
Run Code Online (Sandbox Code Playgroud)
然后我打开文件,创建一个filter_lines-generator(这里我需要知道stride),并将该生成器传递给genfromtxt:
with open(fname) as f:
data = np.genfromtxt(filter_lines(f, 8),
dtype='f',
usecols=(1, 2, 3))
Run Code Online (Sandbox Code Playgroud)
这很轻松.请注意,我可以用来usecols摆脱数据的第一列.以同样的方式,您可以使用所有其他功能genfromtxt- 检测类型,从列到列的不同类型,缺失值,转换器等.
在这个例子data.shape中(204000, 3),原始文件由272000行组成.
这里generator用于过滤均匀跨步的线,但是同样可以想象它基于(简单)标准过滤掉不均匀的线块.
这是regexp我要使用的:
regexp = r'\s+\w+' + r'\s+([-.0-9]+)' * 3 + r'\s*\n'
Run Code Online (Sandbox Code Playgroud)
组 - 即内部()- 定义要从给定线提取的标记.接下来,fromregex完成工作并忽略与模式不匹配的行:
data = np.fromregex(fname, regexp, dtype='f')
Run Code Online (Sandbox Code Playgroud)
结果与第一种方法完全相同.
| 归档时间: |
|
| 查看次数: |
5977 次 |
| 最近记录: |