【问题标题】:How do create new column in csv file using python by shifting one row如何通过移动一行使用python在csv文件中创建新列
【发布时间】:2014-09-10 18:59:46
【问题描述】:

我有如下 CSV 文件。这是一个包含数千条记录的巨大文件。

输入.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

我想通过在第一列“否”之后添加新列“PSR”来创建 output.csv 文件。此列值取决于列“PSR”值。对于第一行,“PSR”应为零。从下一条记录开始,它取决于上一行中的“CSR”值。如果当前和先前记录的 CSR 值相同,则“PSR”应为零。如果不是,则 PSR 值应具有先前的 CSR 值。例如,第 2 行 CSR 的值为 1300,这与第 1 条记录中的值不同(它是 1200)。所以第 2 行的 PSR 值应为 1200。第 2 行和第 3 行的 CSR 值相同。因此,第 3 行的 PSR 值应为零。因此,新值 PSR 取决于当前和先前字段中的 CSR 值。

输出.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

我的方法:

  1. 使用 csv.reader 并遍历列表中的对象。将第 5 列复制到列表中的第 2 列。向下移动一排。
  2. 然后检查第 2 列和第 5 列(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)

【问题讨论】:

    标签: python list csv


    【解决方案1】:

    如果您对非 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 
    

    【讨论】:

      【解决方案2】:

      只需按照您的说明进行编码即可。存储上一个 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)
      

      【讨论】:

        【解决方案3】:
        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)
        

        【讨论】:

        • 谢谢。该解决方案也有效。但我无法将多个帖子标记为答案。
        【解决方案4】:

        或者,使用csvDictReaderDictWriter 功能更容易:

        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)
        

        【讨论】:

        • 谢谢。我认为 DictReader 是不错的选择。我将尝试学习如何使用它。但是我的脚本出现以下错误。 with open('input.csv', 'rb') as in_file, open('output.csv', 'wb') as out_file: ^ SyntaxError: invalid syntax
        • 你有什么版本的 Python?此语法是在 2.7/3.1 中添加的
        • Python 2.6.6。它也失败了 python-3.4.1
        • 箭头到底指向什么?所以显然不维护 cmets 中的间距
        • 没有 pbm。在更正语法以匹配我的 PERL 版本后,我让它工作了。
        猜你喜欢
        • 2017-08-31
        • 2015-05-02
        • 2021-11-15
        • 1970-01-01
        • 2023-03-16
        • 1970-01-01
        • 1970-01-01
        • 2020-06-15
        • 1970-01-01
        相关资源
        最近更新 更多