【问题标题】:Reading last N rows of a large csv in Pandas在 Pandas 中读取大 csv 的最后 N 行
【发布时间】:2019-08-16 14:04:09
【问题描述】:

我有 50 GB 数据的文件。我知道如何使用 Pandas 进行数据分析。
我只需要大的 1000 行或行,并且需要完整的 50 GB。
因此,我想到在read_csv() 中使用nrows 选项。
我写了这样的代码:

import pandas as pd
df = pd.read_csv("Analysis_of_50GB.csv",encoding="utf-16",nrows=1000,index_col=0)

但它占据了前 1000 行。我需要最后 100 行。所以我这样做并收到错误:

df = pd.read_csv("Analysis_of_50GB.csv",encoding="utf-16",nrows=-1000,index_col=0)
ValueError: 'nrows' must be an integer >=0

我什至尝试在read_csv() 中使用chunksize。但它仍然加载完整的文件。甚至输出也不是DataFrame,而是iterables

因此,请告诉我在这种情况下我能做些什么。

请注意,我不想打开完整的文件...

【问题讨论】:

  • @SukumarRdjf 我不想加载整个文件。请在标记为重复之前仔细阅读问题。
  • 您知道文件中行数或行长的近似值吗?
  • 不,先生。我需要数一数。我想这是不可行的,因为我需要打开文件并计数。
  • @EdChum 它接近于stackoverflow.com/questions/17108250/… 的副本,但不是数据帧的最后一行!重点是不要将整个文件加载到数据框中......

标签: python pandas


【解决方案1】:

纯熊猫方法:

import pandas as pd
line = 0
chksz = 1000
for chunk in pd.read_csv("Analysis_of_50GB.csv",encoding="utf-16",chunksize = chksz,index_col=0, usecols=0):
    line += chunk.shape[0]

所以这只是计算行数,出于性能原因,我们只读取第一列。

一旦我们有了总行数,我们就从最后减去我们想要的行数:

df = pd.read_csv("Analysis_of_50GB.csv",encoding="utf-16", skiprows = line - 1000,index_col=0)

【讨论】:

    【解决方案2】:

    按照Efficiently Read last 'n' rows of CSV into DataFrame 接受的答案中的建议,通常的方法是读取整个文件并在出队中保留 1000 行。但对于 50GB 的非常大的文件,它可能不是最佳选择。

    在这种情况下,我会尝试一个简单的预处理:

    • 打开文件
    • 读取并丢弃 1000 行
    • 使用 ftell 获得目前已阅读内容的近似值
    • 从文件末尾查找该大小并在大缓冲区中读取文件末尾(如果您有足够的内存)
    • 将 '\n' 字符在缓冲区中的位置存储在大小为 1001 的 dequeue 中(文件可能有一个终端 '\n'),我们称之为deq
    • 确保有 1001 个换行符,否则使用更大的偏移量进行迭代
    • 使用缓冲区中包含的 1000 行加载数据帧:

      df = pd.read_csv(io.StringIO(buffer[d[0]+1:]))
      

    代码可能是(注意:未经测试):

    with open("Analysis_of_50GB.csv", "r", encoding="utf-16") as fd:
        for i in itertools.islice(fd, 1250):      # read a bit more...
            pass
        offset = fd.tell()
        while(True):
            fd.seek(-offset, os.SEEK_END)
            deq = collection.deque(maxlen = 1001)
            buffer = fd.read()
            for i,c in enumerate(buffer):
                if c == '\n':
                    deq.append(i)
            if len(deq) == 1001:
                break
            offset = offset * 1250 // len(deq)
    
    df = pd.read_csv(io.StringIO(buffer[d[0]+1:]))
    

    【讨论】:

    • 这可能会有所帮助..但是会消耗很多时间我想我会尝试一下...
    • @JafferWilson:不确定,因为它可以为大文件节省大量磁盘 io。我很想知道结果...
    【解决方案3】:

    您应该考虑使用dask,它在后台进行分块并允许您处理非常大的数据帧。它的工作流程与 pandas 非常相似,并且最重要的功能已经实现。

    【讨论】:

      【解决方案4】:

      我认为您需要同时使用 skiprows 和 nrows。假设您的文件有 1000 行,那么,

      df =pd.read_csv('"Analysis_of_50GB.csv", encoding="utf16",skiprows = lambda x: 0<x<=900, nrows=1000-900,index_col=0)
      

      读取从 901 到 1000 的所有行。

      【讨论】:

        猜你喜欢
        • 2016-12-06
        • 2018-09-10
        • 2016-01-28
        • 1970-01-01
        • 2018-12-04
        • 1970-01-01
        • 1970-01-01
        • 2011-05-06
        • 1970-01-01
        相关资源
        最近更新 更多