Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从csv文件逐块读取和反转数据,并复制到新的csv文件_Python_Python 3.x_Pandas_Csv_Dataset - Fatal编程技术网

Python 从csv文件逐块读取和反转数据,并复制到新的csv文件

Python 从csv文件逐块读取和反转数据,并复制到新的csv文件,python,python-3.x,pandas,csv,dataset,Python,Python 3.x,Pandas,Csv,Dataset,假设我正在处理一个非常大的csv文件。因此,我只能将数据逐块读取到内存中。预期的事件流应如下所示: 1) 使用pandas从csv读取数据块(例如:10行) 2) 颠倒数据顺序 3) 将每一行反向复制到新的csv文件。因此,每个块(10行)是 按相反顺序从一开始写入csv 最后,csv文件的顺序应该是相反的,这应该在不将整个文件加载到windows操作系统内存的情况下完成 我正在尝试做一个时间序列预测,我需要的数据从旧到最新(第一行最旧的条目)。我无法将整个文件加载到内存中。如果可能的话,我正在

假设我正在处理一个非常大的csv文件。因此,我只能将数据逐块读取到内存中。预期的事件流应如下所示:

1) 使用pandas从csv读取数据块(例如:10行)

2) 颠倒数据顺序

3) 将每一行反向复制到新的csv文件。因此,每个块(10行)是 按相反顺序从一开始写入csv

最后,csv文件的顺序应该是相反的,这应该在不将整个文件加载到windows操作系统内存的情况下完成

我正在尝试做一个时间序列预测,我需要的数据从旧到最新(第一行最旧的条目)。我无法将整个文件加载到内存中。如果可能的话,我正在寻找一种方法一次完成每个块

我在kaggle的
train.csv
上尝试的数据集。你可以从这里得到它

我的尝试没有正确地将行复制到新的csv文件中

下面是我的代码:

import pandas as pd
import csv

def reverse():

    fields = ["Store","DayOfWeek","Date","Sales","Customers","Open","Promo","StateHoliday",
              "SchoolHoliday"]
    with open('processed_train.csv', mode='a') as stock_file:
        writer = csv.writer(stock_file,delimiter=',', quotechar='"', 
                                                quoting=csv.QUOTE_MINIMAL)
        writer.writerow(fields)

    for chunk in pd.read_csv("train.csv", chunksize=10):
        store_data = chunk.reindex(index=chunk.index[::-1])
        append_data_csv(store_data)

def append_data_csv(store_data):
    with open('processed_train.csv', mode='a') as store_file:
        writer = csv.writer(store_file,delimiter=',', quotechar='"',
                                           quoting=csv.QUOTE_MINIMAL)
        for index, row in store_data.iterrows():
            print(row)
            writer.writerow([row['Store'],row['DayOfWeek'],row['Date'],row['Sales'],
            row['Customers'],row['Open'],row['Promo'],
            row['StateHoliday'],row['SchoolHoliday']])

reverse()

谢谢你,事先你有重复的代码块,你根本没有利用熊猫

@sujay kumar指出的是非常正确的,我会仔细阅读

这个文件一点也不大。我使用的OHLCV刻度数据以GBs为单位,没有问题。如果您使用pandas.read\u csv()您不必进行分块传输。当然这需要时间,但会很好。除非你要去Terrabytes。我还没有测试过

当您
读取\u csv()
时,您不会指定任何索引。如果您这样做了,您可以调用
sort\u index()

熊猫也可以写CSV,请改用它。我正在粘贴一些示例代码供您组合

df_temp=pd.read_csv(文件路径,解析日期=True,索引col=“Date”,
usecols=[“日期”,“调整结束”],na_值=[“nan”])

对序列进行排序

s=pd.系列(列表('abcde'),索引=[0,3,2,5,4])
s、 排序索引()


注意:如果您坚持使用Pandas及其函数,您将运行已经优化的代码,而不需要将整个文件加载到内存中。这很容易,就像作弊一样:)

如果你有足够的硬盘空间,你可以分块读取、反转和存储。然后以相反的顺序提取存储的块并写入一个新的csv文件

下面是熊猫的一个例子,它也使用pickle(用于性能效率)和gzip(用于存储效率)


我不建议使用
pandas
解析或流式传输任何文件,因为这只会增加额外的开销。最好的方法是自下而上读取文件。这个代码的很大一部分实际上来自于它接收文件并在生成器中返回相反的结果,我相信这就是你想要的

我所做的只是使用您提供的链接中的文件
train.csv
对其进行测试,并将结果输出到一个新文件中

import os

def reverse_readline(filename, buf_size=8192):
    """a generator that returns the lines of a file in reverse order"""
    with open(filename) as fh:
        segment = None
        offset = 0
        fh.seek(0, os.SEEK_END)
        file_size = remaining_size = fh.tell()
        while remaining_size > 0:
            offset = min(file_size, offset + buf_size)
            fh.seek(file_size - offset)
            buffer = fh.read(min(remaining_size, buf_size))
            remaining_size -= buf_size
            lines = buffer.split('\n')
            # the first line of the buffer is probably not a complete line so
            # we'll save it and append it to the last line of the next buffer
            # we read
            if segment is not None:
                # if the previous chunk starts right from the beginning of line
                # do not concact the segment to the last line of new chunk
                # instead, yield the segment first 
                if buffer[-1] != '\n':
                    lines[-1] += segment
                else:
                    yield segment
            segment = lines[0]
            for index in range(len(lines) - 1, 0, -1):
                if lines[index]:
                    yield lines[index]
        # Don't yield None if the file was empty
        if segment is not None:
            yield segment

reverse_gen = reverse_readline('train.csv')

with open('rev_train.csv','w') as f:
    for row in reverse_gen:
        f.write('{}\n'.format(row))

它基本上是反向读取,直到找到一个换行符,然后从文件的底部到顶部生成一行。这是一种非常有趣的方式

这完全符合您的要求,但没有熊猫。它逐行读取intest.csv(而不是将整个文件读入RAM)。它使用文件系统执行大部分处理,使用一系列块文件,这些块文件最后聚合到outtest.csv文件中。如果更改最大行数,则可以优化生成的块文件数,而不是消耗的RAM数(数字越大,消耗的RAM越多,但生成的块文件越少)。如果要保留CSV头的第一行,请将keepHeader设置为True;如果设置为False,则会反转整个文件,包括第一行

为了好玩,我在一个6MB csv测试文件上使用128GB闪存驱动器在一个旧的Raspberry Pi上运行了这个程序,我认为出现了一些问题,因为它几乎立即返回,所以即使在较慢的硬件上也很快。它只导入一个标准python库函数(remove),因此它非常可移植。此代码的一个优点是它不会重新定位任何文件指针。一个限制是,它不能用于数据中有换行符的CSV文件。对于该用例,pandas将是读取块的最佳解决方案

from os import remove

def writechunk(fileCounter, reverseString):
    outFile = 'tmpfile' + str(fileCounter) + '.csv'
    with open(outFile, 'w') as outfp:
        outfp.write(reverseString)
    return

def main():
    inFile = 'intest.csv'
    outFile = 'outtest.csv'
    # This is our chunk expressed in lines
    maxLines = 10
    # Is there a header line we want to keep at the top of the output file?
    keepHeader = True

    fileCounter = 0
    lineCounter = 0
    with open(inFile) as infp:
        reverseString = ''
        line = infp.readline()
        if (line and keepHeader):
            headerLine = line
            line = infp.readline()
        while (line):
            lineCounter += 1
            reverseString = line + reverseString
            if (lineCounter == maxLines):
                fileCounter += 1
                lineCounter = 0
                writechunk(fileCounter, reverseString)
                reverseString = ''
            line = infp.readline()
    # Write any leftovers to a chunk file
    if (lineCounter != 0):
        fileCounter += 1
        writechunk(fileCounter,reverseString)
    # Read the chunk files backwards and append each to the outFile
    with open(outFile, 'w') as outfp:
        if (keepHeader):
            outfp.write(headerLine)
        while (fileCounter > 0):
            chunkFile = 'tmpfile' + str(fileCounter) + '.csv'
            with open(chunkFile, 'r') as infp:
                outfp.write(infp.read())
            remove(chunkFile)
            fileCounter -= 1

if __name__ == '__main__':
    main()

使用bash,您可以跟踪除第一行以外的整个文件,然后将其反转并使用以下命令存储:

tail -n +2 train.csv  | tac > train_rev.csv
如果要将标题保留在已反转的文件中,请先将其写入,然后追加已反转的内容

head -1 train.csv > train_rev.csv; tail -n +2 train.csv  | tac >> train_rev.csv

您希望对整个数据进行时间排序,但从一开始就一次对10个数据进行排序和写入。这就是为什么你没有得到结果。为什么不从末尾读取并反转train.csv。看,我试过前面那篇文章中给出的代码。但它没有给我一个合适的结果。你能详细说明吗?你到底得到了什么?如果可能的话,将文件上传到dropbox中。下载文件的过程太长,(要下载该文件,用户必须登录、注册然后填写信息…等等…)只是为了下载文件。注意:这不是一个完美的解决方案。但是,您可以使用cmd行tail-r train.csv>reverse.csv简单地还原文件。然后手动删除最后一行并将其添加到reverse.csv中的第一行。实际上,每个文件块都应该反转,接下来每个反转的行块都应该在前面加上前缀,而不是附加到csv文件中。因此,整个文件将在最后被反转,但不将整个文件加载到内存中,而是逐块反转。@SaiKumar,明白了,已经用一个执行完全反转的解决方案进行了更新。如果使用UTF-8,这实际上会导致重叠和丢失文本块。您不能只在可变宽度编码文件中查找!接下来,如果CSV文件在单元格值中嵌入了换行符,则反转不能只是在换行符上任意拆分。接下来,符合RFC的CSV文件将使用
\r\n
行分隔符
head -1 train.csv > train_rev.csv; tail -n +2 train.csv  | tac >> train_rev.csv