Python将文本文件逐行加载到numpy数组中

时间:2017-09-30 02:19:20

标签: python arrays numpy

我有一个以下格式的文本文件,其中每一行用换行符分隔

a 0.418 0.24968 -0.41242 0.1217 0.34527 -0.044457 -0.49688 -0.17862 -0.00066023 -0.6566
b 0.013441 0.23682 -0.16899 0.40951 0.63812 0.47709 -0.42852 -0.55641 -0.364 -0.23938
c 0.15164 0.30177 -0.16763 0.17684 0.31719 0.33973 -0.43478 -0.31086 -0.44999 -0.29486

我正在尝试将每行的数字组件加载到形状为3x10的numpy数组中。这是我一直在使用的方法。

embeddings = np.empty((0, 50))
for line in f :
            splitLine = line.rstrip().split()
            res = splitLine[1:]
            embeddings = np.append(embeddings, [res], axis=0)

然而,当行数增加时(我有一个包含400000行的文本文件),这种方法变得非常耗时。

是否有更有效的方法将数值加载到numpy数组?

3 个答案:

答案 0 :(得分:0)

使用Pandas'read_table代替,然后将DataFrame转换为您需要的numpy数组。它会比尝试拆分字符串并逐行组装数组更快更干净。

答案 1 :(得分:0)

是的,这是因为numpy数组是固定大小的,np.append是O(N)操作。最好的办法是加载到列表中,然后使用该列表创建numpy.array。如果该列表可能变得太大并且给你带来内存问题,那么只需使用np.fromiter,它就会比你的方法更慢,但比加载到列表中的内存效率更高。首先,一些设置:

>>> s = """a 0.418 0.24968 -0.41242 0.1217 0.34527 -0.044457 -0.49688 -0.17862 -0.00066023 -0.6566
... b 0.013441 0.23682 -0.16899 0.40951 0.63812 0.47709 -0.42852 -0.55641 -0.364 -0.23938
... c 0.15164 0.30177 -0.16763 0.17684 0.31719 0.33973 -0.43478 -0.31086 -0.44999 -0.29486"""
>>>
>>> import io
>>> import numpy as np

最后,尝试将count参数传递给np.fromiter

>>> import csv
>>> with io.StringIO(s) as f: # fake a file
...     reader = csv.reader(f, delimiter=' ')
...     vals = (float(x) for row in reader for x in row[1:])
...     arr = np.fromiter(vals, count=10*3, dtype=float)
...
>>> arr
array([ 0.418     ,  0.24968   , -0.41242   ,  0.1217    ,  0.34527   ,
       -0.044457  , -0.49688   , -0.17862   , -0.00066023, -0.6566    ,
        0.013441  ,  0.23682   , -0.16899   ,  0.40951   ,  0.63812   ,
        0.47709   , -0.42852   , -0.55641   , -0.364     , -0.23938   ,
        0.15164   ,  0.30177   , -0.16763   ,  0.17684   ,  0.31719   ,
        0.33973   , -0.43478   , -0.31086   , -0.44999   , -0.29486   ])

最后,假设您知道尺寸,将形状更改为您需要的形状:

>>> arr.shape = (3, 10)
>>> arr
array([[ 0.418     ,  0.24968   , -0.41242   ,  0.1217    ,  0.34527   ,
        -0.044457  , -0.49688   , -0.17862   , -0.00066023, -0.6566    ],
       [ 0.013441  ,  0.23682   , -0.16899   ,  0.40951   ,  0.63812   ,
         0.47709   , -0.42852   , -0.55641   , -0.364     , -0.23938   ],
       [ 0.15164   ,  0.30177   , -0.16763   ,  0.17684   ,  0.31719   ,
         0.33973   , -0.43478   , -0.31086   , -0.44999   , -0.29486   ]])

如果提前知道行数,您可以快速首先通过并计算它们,例如:

>>> with io.StringIO(s) as f:
...     num_rows = sum(1 for row in f)
...
>>> num_rows
3

答案 2 :(得分:0)

numpy中的普通加载器为loadtxtgenfromtxt。在这种情况下,两者都易于使用:

In [129]: lines = b"""a 0.418 0.24968 -0.41242 0.1217 0.34527 -0.044457 -0.49688
     ...:  -0.17862 -0.00066023 -0.6566
     ...: b 0.013441 0.23682 -0.16899 0.40951 0.63812 0.47709 -0.42852 -0.55641 
     ...: -0.364 -0.23938
     ...: c 0.15164 0.30177 -0.16763 0.17684 0.31719 0.33973 -0.43478 -0.31086 -
     ...: 0.44999 -0.29486"""
In [130]: lines = lines.splitlines()

由于您对第一栏不感兴趣,我们可以跳过它:

In [134]: arr = np.genfromtxt(lines,usecols=range(1,11))
In [135]: arr
Out[135]: 
array([[ 0.418     ,  0.24968   , -0.41242   ,  0.1217    ,  0.34527   ,
        -0.044457  , -0.49688   , -0.17862   , -0.00066023, -0.6566    ],
       [ 0.013441  ,  0.23682   , -0.16899   ,  0.40951   ,  0.63812   ,
         0.47709   , -0.42852   , -0.55641   , -0.364     , -0.23938   ],
       [ 0.15164   ,  0.30177   , -0.16763   ,  0.17684   ,  0.31719   ,
         0.33973   , -0.43478   , -0.31086   , -0.44999   , -0.29486   ]])

这将逐行读取文件(此处使用行列表进行模拟),解析每个文件并将结果累积到列表中。这比每次附加到数组要快。

为了更快地使用pandas阅读器 - 它同时具有C和Python引擎。

In [140]: pd.read_csv(BytesIO(b'\n'.join(lines)), delim_whitespace=True,header=N
     ...: one,usecols=range(1,11)).values
Out[140]: 
array([[ 0.418     ,  0.24968   , -0.41242   ,  0.1217    ,  0.34527   ,
        -0.044457  , -0.49688   , -0.17862   , -0.00066023, -0.6566    ],
       [ 0.013441  ,  0.23682   , -0.16899   ,  0.40951   ,  0.63812   ,
         0.47709   , -0.42852   , -0.55641   , -0.364     , -0.23938   ],
       [ 0.15164   ,  0.30177   , -0.16763   ,  0.17684   ,  0.31719   ,
         0.33973   , -0.43478   , -0.31086   , -0.44999   , -0.29486   ]])

至少每个人都声称大熊猫的速度更快 - 对于这个小样本来说,它不是:

In [141]: timeit pd.read_csv(BytesIO(b'\n'.join(lines)), delim_whitespace=True,h
     ...: eader=None,usecols=range(1,11)).values
1.31 ms ± 18.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [142]: timeit arr = np.genfromtxt(lines,usecols=range(1,11))
380 µs ± 17.1 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)