【问题标题】:How to replace a column using Python's built-in .csv writer module?如何使用 Python 的内置 .csv 编写器模块替换列?
【发布时间】:2010-11-04 09:18:48
【问题描述】:

我需要在一个巨大的 Excel .csv 文件中进行查找和替换(特定于一列 URL)。由于我正处于尝试自学脚本语言的开始阶段,我想我会尝试在 python 中实现该解决方案。

我在解决方案的“替换”部分遇到问题。我已经阅读了official csv module documentation 关于如何使用编写器的内容,但对我来说并没有一个足够清晰的例子(是的,我很慢)。那么,现在的问题是:如何使用 writer 对象遍历 csv 文件的行?

附言提前为笨拙的代码道歉,我还在学习:)

import csv

csvfile = open("PALTemplateData.csv")
csvout = open("PALTemplateDataOUT.csv")
dialect = csv.Sniffer().sniff(csvfile.read(1024))
csvfile.seek(0)
reader = csv.reader(csvfile, dialect)
writer = csv.writer(csvout, dialect)

total=0;
needchange=0;
changed = 0;
temp = ''
changeList = []

for row in reader:
    total=total+1
    temp = row[len(row)-1]
    if '/?' in temp:
        needchange=needchange+1;
        changeList.append(row.index)

for row in writer:           #this doesn't compile, hence the question
    if row.index in changeList:
        changed=changed+1
        temp = row[len(row)-1]
        temp.replace('/?', '?')
        row[len(row)-1] = temp
        writer.writerow(row)

print('Total URLs:', total)
print('Total URLs to change:', needchange)
print('Total URLs changed:', changed)

【问题讨论】:

  • 启动时 PALTemplateDataOUT.csv 是否为空?
  • 不,它与输入文件完全相同(具有所有相同的数据)我只是不想意外覆盖我需要的任何内容
  • “意外覆盖”是什么意思?通常我们读取一个文件并写入一个不同的文件。
  • 我想你是对的 - 拥有这么多副本非常愚蠢(更不用说糟糕的“做法”)。

标签: python file-io csv


【解决方案1】:

您收到错误的原因是编写器没有要迭代的数据。你应该给它数据 - 大概,你会有某种列表或生成器来生成要写出的行。

我建议将这两个循环组合起来,如下所示:

for row in reader:
    row[-1] = row[-1].replace('/?', '?')
    writer.writerow(row)

这样,您甚至不需要total、needchange 和changeList。 (其中有很多优化,很遗憾我没有时间解释,但我会看看我是否可以稍后编辑这些信息)

【讨论】:

  • 请记住,这样做会覆盖您的输出文件。这是做这种事情的典型方式。从文件的两个副本开始,就像你上面那样,不是最佳做法。
  • +1:就此而言,您通常也不需要嗅探器或 seek(0)。
  • 这当然是一个优雅的解决方案,但是,我认为您不能在 for 循环迭代和 writerow() 的参数中使用相同的“行”引用。解释器说:“io.UnsupportedOperation: BufferedReader.write() not supported”
  • @ignorantslut: write() 当然不支持。但是,应该支持writerow()。检查您的代码以确保您正确拼写方法名称。
  • @S. Lott:我直接从 David 的示例中复制和粘贴。完整追溯:文件“C:\Documents and Settings\g41092\My Documents\palScript.py”,第 21 行,在 writer.writerow(row) 文件“C:\Program Files\Python\lib\io.py ",第 1495 行,写入 self.buffer.write(b) 文件 "C:\Program Files\Python\lib\io.py",第 701 行,写入 self._unsupported("write") 文件 "C:\ Program Files\Python\lib\io.py",第 322 行,在 unsupported (self.__class_.__name__, name)) io.UnsupportedOperation: BufferedReader.write() 不支持
【解决方案2】:

您应该只有一个循环并同时读取和写入 - 如果您的替换一次只影响一行,您不需要循环两次数据。

for row in reader:
  total=total+1
  temp = row[len(row)-1]
  if '/?' in temp:
    temp = row[len(row)-1]
    temp.replace('/?', '?')
    row[len(row)-1] = temp
  writer.writerow(row)

这只是为了说明循环,不确定替换代码是否会这样工作。

【讨论】:

    【解决方案3】:

    一旦将 csv 放入大列表中,替换列表中列的一种简单方法是转置矩阵,替换行,然后将其转回:

    mydata = [[1, 'a', 10], [2, 'b', 20], [3, 'c', 30]]
    
    def transpose(matrix):
        return [[matrix[x][y] for x in range(len(matrix))] for y in range(len(matrix[0]))]
    
    transposedData = transpose(mydata)
    print transposedData
    >>> [[1, 2, 3], ['a', 'b', 'c'], [10, 20, 30]]
    
    editedData = transposedData[:2] + [50,70,90]
    print editedData
    >>> [[1, 2, 3], ['a', 'b', 'c'], [50, 70, 90]]
    
    mydata = transpose(editedData)
    print mydata
    >>> [[1, 'a', 50], [2, 'b', 70], [3, 'c', 90]]
    

    【讨论】:

      猜你喜欢
      • 2010-11-04
      • 1970-01-01
      • 2020-02-15
      • 1970-01-01
      • 2018-12-24
      • 2016-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多