【问题标题】:load a certain number of rows from csv with numpy使用 numpy 从 csv 加载一定数量的行
【发布时间】:2015-10-28 06:12:08
【问题描述】:

我有一个很长的文件,我只需要它的一部分,一个切片。 有新数据传入,因此文件可能会变长。

要从 CSV 加载数据,我使用 numpy.genfromtxt

    np.genfromtxt(filename, usecols={col}, delimiter=",", skip_header=skip_head)

这会在开始时切断文件的某些部分,这已经大大加快了加载数据的过程。 但是我最终不能使用skip_footer 来切断我想要使用的切片之后的部分。

我想要的是只加载一定数量的行。例如假设我跳过前 100 行,然后加载接下来的 50 行,然后跳过其余的。

编辑:我使用的是 Python 3.4
编辑:示例文件:http://www.file-upload.net/download-10819938/sample.txt.html

【问题讨论】:

    标签: python csv numpy genfromtxt


    【解决方案1】:

    Numpy 1.10 开始,np.genfromtxt 带有一个可选参数max_rows,它限制了要读取的行数。

    结合其他可选参数skip_header,您可以选择文件的一部分(例如第100到150行):

    import numpy as np
    
    np.loadtxt('file.txt', skip_header=100, max_rows=50)
    

    【讨论】:

      【解决方案2】:

      您可以使用 itertools 获取切片,使用 itemgetter 获取列:

      import  numpy as np
      from operator import itemgetter
      import csv
      with open(filename) as f:
         from itertools import islice,imap
         r = csv.reader(f)
         np.genfromtxt(imap(itemgetter(1),islice(r,  start, end+1)))
      

      对于python3,你可以使用fromiter,上面的代码你需要指定dtype:

      import numpy as np
      from operator import itemgetter
      import csv
      with open("sample.txt") as f:
         from itertools import islice
         r = csv.reader(f)
         print(np.fromiter(map(itemgetter(0), islice(r,  start, end+1)), dtype=float))
      

      与其他答案一样,您也可以将 islice 对象直接传递给 genfromtxt 但对于 python3,您需要以二进制模式打开文件:

      with open("sample.txt", "rb") as f:
          from itertools import islice
          print(np.genfromtxt(islice(f, start, end+1), delimiter=",", usecols=cols))
      

      有趣的是,对于使用 itertools.chain 的多个列,如果所有 dtype 都相同,那么整形的效率会提高一倍以上:

      from itertools import islice,chain
      with open("sample.txt") as f:
         r = csv.reader(f)
         arr =np.fromiter(chain.from_iterable(map(itemgetter(0, 4, 10), 
                                                  islice(r,  4, 10))), dtype=float).reshape(6, -1) 
      

      在你的示例文件上:

      In [27]: %%timeit
      with open("sample.txt", "rb") as f:
          (np.genfromtxt(islice(f, 4, 10), delimiter=",", usecols=(0, 4, 10),dtype=float))
         ....: 
      
      10000 loops, best of 3: 179 µs per loop
      
      In [28]: %%timeit
      with open("sample.txt") as f:
         r = csv.reader(f)                                                               (np.fromiter(chain.from_iterable(map(itemgetter(0, 4, 10), islice(r,  4, 10))), dtype=float).reshape(6, -1))
      
      10000 loops, best of 3: 86 µs per loop
      

      【讨论】:

      • 嗯,我无法导入 imap。我认为这是因为我使用的是 python 3.4
      • 只用map和python 3
      • 你的意思是把 imap 换成 map 吗?
      • 反正原代码有错误,需要使用csv模块来拆分数据。您可以添加您的文件示例,以便我可以在本地运行它吗?
      • 现在我得到 TypeError: 'Can't convert 'bytes' object to str implicitly'
      【解决方案3】:

      this example之后,你应该可以使用itertools.islice,而不需要imapmapcsv.reader

      import numpy as np
      import itertools
      
      with open('sample.txt') as f:
          # this will skip 100 lines, then read the next 50
          d=np.genfromtxt(itertools.islice(f,100,150),delimiter=',',usecols={cols})
      

      【讨论】:

      • 我试过了,我得到了 TypeError: 'Can't convert 'bytes' object to str implicitly'
      猜你喜欢
      • 1970-01-01
      • 2019-07-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-17
      相关资源
      最近更新 更多