csv Pandas只阅读文本文件的第一行、倒数第二行和最后一行

jucafojl  于 5个月前  发布在  其他
关注(0)|答案(3)|浏览(74)

由于我只需要txt文件中索引为0,-2 & -1的行,并且想优化代码的速度(我将要处理的文本文件在某个时候会变得很长),我想问一下是否有人知道是否可以避免加载整个文件而只加载所需的行。我遇到了下面的代码,我认为这将是这个问题的完美解决方案:

rows_wanted = [0,-2,-1]    
data = pd.read_csv(txt_path, skiprows = lambda x: x not in rows_wanted)

字符串
不幸的是,这似乎不适用于负索引,因为输出仅包含第一行。因此,我想只计算对应于-2 & -的正指数值1通过获取文件中的行的总量,但我还没有找到一个解决方案,它本身并不需要加载整个文件。我也遇到了头和尾方法的Pandas,但至于我明白这些也只有在加载整个文件后才有用。

dsf9zpds

dsf9zpds1#

我不认为pd.rad_csv有一个很好的方法来做你想做的事情,一个选择是使用how to efficiently get line count的答案,并在代码中使用它

# file_name = 'myfile.csv'
num_lines = sum(1 for _ in open(file_name))

rows_wanted = [x if x>= 0 else num_lines + x for x in rows_wanted]
pd.read_csv('titanic.csv', skiprows= lambda x: x not in rows_wanted)

字符串

noj0wjuj

noj0wjuj2#

对于大文件,一种优化的方法是以 binary 模式打开文件,然后从f.seek结尾开始移动文件指针,检测2个换行符b'\n'(表示各自的最后2行),并将这些行作为io.BinaryIO读入一个字符串。
样品:

import os
import io

fname = 'test.csv'

with open(fname, 'rb') as f:
    head = f.readline() # read the 1st line (head)
    f.seek(-2, os.SEEK_END) # forward file pointer 2 bytes from the end
    n = 2

    while n:
        f.seek(-2, os.SEEK_CUR) # move file pointer backward
        if f.read(1) == b'\n': # catch a linebreak
            n -= 1

    df = pd.read_csv(io.BytesIO(head + f.read()))

字符串

monwx1rj

monwx1rj3#

一种尊重文本编码和可能引用的换行符等的方法是使用csvdeque来存储“最后n”行:

import csv
from collections import deque

def row_selector_gen(file, rows, **fmtargs):
    buflen = max(1, 1 - min(rows))
    buflines = deque(maxlen=buflen)
    reader = csv.reader(file, **fmtargs)
    for i, row in enumerate(reader):
        if i in rows:
            yield row
            buflines.append(None)
        else:
            buflines.append(row)
    for i in sorted([i for i in rows if i < 0]):
        try:
            row = buflines[i]
            if row is not None:
                yield row
        except IndexError:
            pass

def row_selector(file, rows, **fmtargs):
    buf = io.StringIO()
    writer = csv.writer(buf, **fmtargs)
    writer.writerows(row_selector_gen(file, rows, **fmtargs))
    buf.seek(0)
    return buf

字符串
范例:

# 1. setup

content = """foo,bar,garçon
1,0.1,"this
and that"
2,0.2,x
3,0.3,y
4,0.4,z
5,0.5,"ha
ha"
"""

with open('test.csv', 'w') as f:
    f.write(content)


然后又道:

with open('test.csv', newline='') as f:
    z = pd.read_csv(row_selector(f, [0, 1, -2, -1]))

>>> z
   foo  bar          garçon
0    1  0.1  this\nand that
1    4  0.4               z
2    5  0.5          ha\nha

限制:

  • 你可能会得到无序的行,例如,如果你在rows中混合了正索引和负索引,或者如果一些负索引引用了一些正索引之前的行。例如,上面的test.csv
with open('test.csv', newline='') as f:
    z = pd.read_csv(row_selector(f, [0, 3, -4, -1]))

>>> z
   foo  bar  garçon
0    3  0.3       y
1    2  0.2       x
2    5  0.5  ha\nha

  • 如果您指定了一个早于文件开头的负数行,它们将被默认跳过:
with open('test.csv', newline='') as f:
    z = pd.read_csv(row_selector(f, [0, 3, -14, -1]))

>>> z
   foo  bar  garçon
0    3  0.3       y
1    5  0.5  ha\nha

相关问题