如何在Python中通过移动一行创建CSV文件的新列
我有一个像下面这样的CSV文件。这个文件很大,里面有成千上万条记录。
input.csv
No;Val;Rec;CSR
0;10;1;1200
0;100;2;1300
0;100;3;1300
0;100;4;1400
0;10;5;1200
0;11;6;1200
我想创建一个output.csv文件,在第一列“No”后面添加一个新列“PSR”。这个新列的值取决于“CSR”列的值。对于第一行,“PSR”的值应该是零。从第二行开始,它的值取决于上一行的“CSR”值。如果当前行和上一行的“CSR”值相同,那么“PSR”的值就为零。如果不相同,PSR的值就等于上一行的“CSR”值。举个例子,第二行的“CSR”值是1300,而第一行的值是1200,所以第二行的“PSR”值应该是1200。而在第二行和第三行中,“CSR”值是相同的,所以第三行的“PSR”值就为零。因此,新的“PSR”值依赖于当前行和上一行的“CSR”值。
Output.csv
No;PCR;Val;Rec;CSR
0;0;10;1;1200
0;1200;100;2;1300
0;0;100;3;1300
0;1300;100;4;1400
0;1400;10;5;1200
0;0;11;6;1200
我的方法:
- 使用csv.reader读取文件,并将对象放入一个列表中。把第五列的值复制到列表的第二列,并向下移动一行。
- 然后检查第二列和第五列(PCR和CSR)的值,如果两个值相同,就把PCR的值替换为零。
我在第一步的编码上遇到了问题。我能复制这一列,但无法将它向下移动。此外,第二步相对简单。
另外,我不确定这个方法是否正确,任何建议或推荐都会很有帮助。
注意:我在CentOS上无法安装Pandas,所以不使用这个模块的帮助会更好。
我的代码:
with open('input.csv', 'r') as input, open('output.csv', 'w') as output:
reader = csv.reader(input, delimiter = ';')
writer = csv.writer(output, delimiter = ';')
mylist = []
header = next(reader)
mylist.append(header)
for rec in reader:
mylist.append(rec)
rec.insert(1, rec[3])
mylist.append(rec)
writer.writerows(mylist)
4 个回答
就按照你说的那样写代码。把之前的CSR存起来,然后在下一次循环的时候用到它;记得要更新它哦。
import csv
with open('input.csv', 'r') as input, open('output.csv', 'w') as output:
reader = csv.reader(input, delimiter = ';')
writer = csv.writer(output, delimiter = ';')
mylist = []
header = next(reader)
mylist.append(header)
mylist.insert(1,'PCR')
prev_csr = 0
for rec in reader:
rec.insert(1,prev_csr)
mylist.append(rec)
prev_csr = rec[4]
writer.writerows(mylist)
或者,更简单的方法是使用 csv
模块里的 DictReader
和 DictWriter
功能:
input_header = ['No','Val','Rec','CSR']
output_header = ['No','PCR','Val','Rec','CSR']
with open('input.csv', 'rb') as in_file, open('output.csv', 'wb') as out_file:
in_reader, out_writer = DictReader(in_file, input_header, delemeter =';'), DictWriter(out_file, output_header, delemeter =';')
in_reader.next() # skip the header
out_writer.writeheader() # place the output header
last_csr = None
for row in in_reader():
current_csr = row['CSR']
row['PCR'] = last_csr if current_csr != last_csr else 0
last_csr = current_csr
out_writer.writerow(row)
在编程中,有时候我们会遇到一些问题,特别是在使用某些工具或库的时候。这些问题可能会让我们感到困惑,但其实只要理解了背后的原理,就能找到解决办法。
比如说,当你在写代码的时候,可能会发现某些功能没有按预期工作。这时候,检查你的代码和使用的工具的文档是很重要的。文档就像是使用说明书,可以告诉你怎么正确使用这些工具。
另外,很多时候,其他开发者也会遇到类似的问题,他们会在网上分享自己的解决方案。像StackOverflow这样的社区就是一个很好的地方,你可以在这里找到别人遇到的问题和解决办法。
总之,遇到问题不要慌,先查查文档,看看有没有人遇到过类似的情况,通常都能找到解决的办法。
with open('input.csv', 'r') as input, open('output.csv', 'w') as output:
reader = csv.reader(input, delimiter = ';')
writer = csv.writer(output, delimiter = ';')
header = next(reader)
header.insert(1, 'PCR')
writer.writerow(header)
prevRow = next(reader)
prevRow.insert(1, '0')
writer.writerow(prevRow)
for row in reader:
if prevRow[-1] == row[-1]:
val = '0'
else:
val = prevRow[-1]
row.insert(1,val)
prevRow = row
writer.writerow(row)
如果你愿意尝试非Python的解决方案,awk
可能是个不错的选择:
awk 'NR==1{$2="PSR;"$2}NR>1{$2=($4==a?0";"$2:+a";"$2);a=$4}1' FS=';' OFS=';' file
No;PSR;Val;Rec;CSR
0;0;10;1;1200
0;1200;100;2;1300
0;0;100;3;1300
0;1300;100;4;1400
0;1400;10;5;1200
0;0;11;6;1200
Awk几乎在所有Linux系统中都有,它就是为了处理这种任务而设计的。它处理文件的速度非常快。你只需在最后加上重定向 > output.csv
,就可以把结果保存到一个文件里。
用简单的python
方法,逻辑是一样的:
#!/usr/bin/env python
last = "0"
with open('input.csv') as csv:
print next(csv).strip().replace(';', ';PSR;', 1)
for line in csv:
field = line.strip().split(';')
if field[3] == last: field.insert(1, "0")
else: field.insert(1, last)
last = field[4]
print ';'.join(field)
这样也能产生相同的结果:
$ python parse.py
No;PSR;Val;Rec;CSR
0;0;10;1;1200
0;1200;100;2;1300
0;0;100;3;1300
0;1300;100;4;1400
0;1400;10;5;1200
0;0;11;6;1200
同样,只需重定向输出,就能保存结果:
$ python parse.py > output.csv