【问题标题】:Python script to remove erroneous characters from a CSV file用于从 CSV 文件中删除错误字符的 Python 脚本
【发布时间】:2018-08-23 21:14:21
【问题描述】:

我有一个自动生成的 CSV 文件,它提供了我需要的数据,但一些单独的单元格中有额外的字符。

COLUMN1           COLUMN2          COLUMN3
'Foo325GoodData'  Bar:388GoodData  383GoodData
'Foo123GoodData'  Bar:998GoodData  293GoodData

我需要在不更改 3 位数据的情况下删除 foo、bar、引号和冒号。

这是我尝试过的代码,但它只是删除了我的所有数据:

 import csv
 import string

 input_file = open('data.csv', 'r')
 output_file = open('data_cleaned.csv', 'w')
 data = csv.reader(input_file)
 writer = csv.writer(output_file,quoting=csv.QUOTE_ALL)
 foo = 'foo'
 bar = '"bar:u'

 for line in data:
     line = str(line)
     new_line = str.replace(line,foo,'')
     new_line2 = str.replace(line,bar,'')
     writer.writerow(new_line.split(','))
     writer.writerow(new_line2.split(','))

按照下面 gboffi 的说明,我尝试了以下方法:

cleaner.py good.csv

 from __future__ import print_function
 from sys import stdin


 q = '"' + "'"
 number = 'foo:'

 print(next(stdin) , end='')

 for line in stdin:

     toks = [tok.strip(q).lstrip(number) for tok in line.split()]

     print(' '.join(toks))

这会生成一个新的 CSV,但似乎没有删除任何不良数据。

【问题讨论】:

  • 你为什么要编写 Python 来做到这一点?为什么不sed
  • 您可以导入 re: 并使用new_line = re.sub('[^0-9 ]+','',str(line))
  • perlsed 一定会更快地解决您的问题
  • 因为你没有空格,你可以使用new_line = re.sub('\\D+','',str(line))
  • 我建议你应用一些基本的调试技巧——你很快就会发现问题。当您创建一个新值时,立即打印出结果变量:linenew_linenew_line2

标签: python python-2.7 csv parsing python-2.x


【解决方案1】:

如果你想删除所有不是数字或空格的东西,为什么不使用这个想法的变体

for line in data:
    print(''.join(c for c in line if c in '0123456789 '))

我们在哪里粘在一起 (''.join(...)) 只有每个输入行中需要的字符?


更新

之前的答案仍然存在,因为它非常适合 OP 最初表达的要求(请参阅问题的编辑历史记录)。

但是,鉴于 OP 给出的要求,他们可以尝试使用以下代码

$ cat nofubar.py 
from sys import stdin

q = '"' + "'"             # we want to remove the 'q'outes
foobar = 'FooBar:'        # and also Foo, Bar and ':' too...

print(next(stdin), end='') # print the header line to stdout, note end=''

for line in stdin:

    # strip quotes on both sides,
    # strip (all) the characters in foobar * only on the left *
    toks = [tok.strip(q).lstrip(foobar) for tok in line.split()]

    print(' '.join(toks))
$

让我们测试一下这个新代码

$ python nofubar.py << END > good.csv
COLUMN1           COLUMN2          COLUMN3
'Foo325GoodData'  Bar:388GoodData  383GoodData
'Foo123GoodData'  Bar:998GoodData  293GoodData
END
$ cat good.csv 
COLUMN1           COLUMN2          COLUMN3
325GoodData 388GoodData 383GoodData
123GoodData 998GoodData 293GoodData
$ 

假设包含无关字符的文件名为bad.csv,您可以在shell 命令行上使用input redirection 符号&lt; 将其连接到stdin

$ python nofubar.py < bad.csv > good.csv
$ 

【讨论】:

  • 我的错,数据不全是数字。既有数字又有文字。
  • 'Foo325GoodData' Bar:388GoodData 383GoodData这一行开始,是325GoodData 388GoodData 383GoodData你想要的吗?无论如何,您能否请edit 提出您的问题并根据您显示的示例数据准确显示您期望的结果
  • 这当然是我正在寻找的输出。在哪里打开源 .csv 文件?
  • 我已经编辑了我的答案以说明您的最后评论。
  • 非常感谢这次更新。我明白你在这里做什么。不知道为什么,但是当我运行它时,我的控制台只是将我踢到 > 提示符。我确实必须导入 future 因为我在 2.7...
【解决方案2】:

注意参数,必须传递给 replace() 方法:第一个参数。是要替换的内容,第二个参数。是用什么来代替。只需从 str.replace(line,bar,'') 中删除行。 replace 是一个方法,第一个“隐藏”参数是 self,这意味着在调用此方法的对象上使用方法,即在您的情况下使用 str var

【讨论】:

  • 你的提示有帮助,我可以让它从一列中删除一组字符......但它不会在两列上做不同的文本,它会在开头和结尾添加括号每一行。
  • 关于引用:尝试在 csv.writer 中使用 csv.QUOTE_NONE 作为引用参数。对于 split() 方法,使用空格作为参数: split(' ')
  • 为什么你认为它不允许我在同一个脚本中更改两个单元格?
【解决方案3】:
foo = 'foo"12jko'
bar = '"bar:u2345'

foo = "".join([i for i in list(foo) if i.isdigit()])
bar = "".join([i for i in list(bar) if i.isdigit()])

print(foo, bar)

结果,

12 2345

根据您的要求调试您的代码。 使用正则表达式是最好的选择。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-19
    • 1970-01-01
    • 1970-01-01
    • 2013-03-22
    • 1970-01-01
    • 2016-11-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多