【问题标题】:Appending two CSV files column-wise按列附加两个 CSV 文件
【发布时间】:2013-11-25 17:51:30
【问题描述】:

假设我在Python 中有两个名为AB 的CSV 文件。

Ahead 看起来像:

 headerNameA1,headerNameA2
 1.12412424,1
 1,1
 1,1
 1,1

Bhead 看起来像:

 headerNameB1,headerNameB2
 1,1
 1,1
 1,1
 1,1

我的目标是将B 附加到A 上,这样A 将如下所示:

 headerNameA1,headerNameA2,headerNameB1,headerNameB2
 1,1,1.12412424,1
 1,1,1,1
 1,1,1,1
 1,1,1,1

从我问的另一个问题来看,这里的代码将采用 AB 并将它们组合成 C

 import csv
 with open('A','rb') as f1, open('B','rb') as f2, open('out.csv','wb') as w:
     writer = csv.writer(w)
     r1,r2 = csv.reader(f1),csv.reader(f2)
     while True:
         try:
             writer.writerow(next(r1)+next(r2))
         except StopIteration:
             break

但是,这个问题的目的只是在A后面加上B

如果A 的大小太大以至于在删除A 之前将其复制为文件C 对磁盘空间来说太昂贵,则这是必要的。

可以接受通过os.system 调用的 bash 解决方案

【问题讨论】:

  • 这些 CSV 文件有多大,它们的组合大小是一个问题?另外,你的代码写for r1, r2 in izip(f1, f2):的方式很奇怪——这是怎么回事?
  • 而且生成的文件也将在远程服务器上?还是您在本地创建它?将要使用该文件的内容 - 不能按原样接受这两个文件吗...多一点上下文会很棒
  • 很好 - 我只是想确定这是否是您真正需要做的事情...如果您坚持要采用这种方法并冒更新 @987654345 的风险@失败,然后你如何重新运行以考虑到这一点 - 祝你好运。我更多地考虑取决于如何使用此文件(您没有在对我的评论的回复中包含该文件),然后您保留两个文件但创建两个文件的“视图”用作“新 A”。
  • A 和 B 是否包含相同的行数?您是否期待另一个更新(我们称之为 C),以便在另一个运行中...... A 应该实际上是 A + B + C 等......?
  • 服务器系统使用的是什么操作系统?

标签: python bash csv io append


【解决方案1】:

您也许可以摆脱命名管道。您有一个 Python 进程运行,它创建一个管道并以写入模式打开它。然后它已经输出到 CSV 文件的按列连接(类似于你所拥有的)......当另一个进程开始读取该文件时,它将能够使用数据,但实际上没有文件被存储在服务器上,它只是按需提供的。当“文件”被消耗掉时,里面就什么都没有了,任何访问它的尝试都会阻塞,直到另一个进程写入另一端。

一些虚拟代码 - 需要更多深思熟虑的异常处理等...:

import os
from itertools import izip

a = 'abcdef' # File A's rows
b = 'ghijkl' # File B's rows

outname = 'joined'

try:
    os.unlink(outname)
    os.mkfifo(outname)
except OSError:
    pass

with open(outname, 'w') as fout:
    for items in izip(a, b):
        fout.write(''.join(items) + '\n') # Do "real" write here instead...
    os.unlink(outname)

其他东西以读取模式打开该“文件”并使用它来检索数据。除非该进程必须具有“物理文件”,否则这应该可以工作...

【讨论】:

  • 您认为这会比复制多个A 然后删除旧的A 慢吗?
  • 这是在权衡...您提到的将涉及创建新 A 的空间和读/写磁盘成本。虽然这使存储成本保持相当稳定,但读取大致相同要求,但是用一次性磁盘写入来换取每次访问的计算成本(很小)......
【解决方案2】:

如果您获得同一个文件的两个文件句柄 - 一个处于“读取”模式,一个处于“更新”模式 (r+b),则应该使用相同的策略。

from itertools import izip
import csv
with open('A','rb') as f1, open('B','rb') as f2, open('A','r+b') as w:
    writer = csv.writer(w)
    for r1,r2 in izip(csv.reader(f1),csv.reader(f2)):
        writer.writerow(r1+r2)

如果可能的话,我建议不要这样做,直接写入第三个文件。

【讨论】:

  • 为什么建议写入第三个文件?如果一个是 10 GB 并且我需要向其中添加大量小文件,这是不可行的。我不想继续为要添加到末尾的每个小文件创建 10 GB 的副本。
  • 此解决方案只是删除第一个文件而不是附加到它。
  • 我刚刚在 Ubuntu 和 windows 上测试了这个,工作正常。至于为什么最好写入第三个文件:嗯,刚刚回答了不是吗?如果出现问题,您的第一个文件就是吐司,无法恢复。磁盘空间便宜,完成后可以清理临时文件。
  • 第一个 toast 文件适合我的用例。还有其他原因吗? (不是讽刺,是真心想知道)。
  • 为了安全起见,我可以只计算底部行中的元素数量与最终A 文件的顶部行中的元素数。如果它们相等,那么我可以假设它工作正常?如果不是,我可以打印一条很好的错误消息(这不是大型应用程序的一部分,我只是在这里编写脚本)。你同意吗?
猜你喜欢
  • 2021-02-19
  • 2016-06-07
  • 2013-11-25
  • 2019-11-06
  • 2014-12-17
  • 2021-11-02
  • 1970-01-01
  • 1970-01-01
  • 2019-09-08
相关资源
最近更新 更多