接合用全行对的一-CSV文件 - 即具备最同第1列值

时间:2014-02-14 14:59:36

标签: python csv merge

确定需要更新主要示例。

我有这个: Joining all rows of a CSV file that have the same 1st column value in Python (首先我必须道歉,因为没有得到如何再次提高...)

我有一个x.CSV文件,如下所示: INT; INT2; STRING; STRING; STRING; STRING; STRING; STRING; STRING; STRING; STRING; and_so_on ......

0; 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;; - 1.0; 0; 0; 1; -1.0

0; 0 ;;;;;;;;;;;;; 30.0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;

0; 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 160.0 ;;; ;;;;;;;;;;;;;;;;;;;

0; 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 0.0; ;;;;;;;;;;;;;;;;;;;

0; 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 0.0 ;;;;;;;;;;;;;;;;;;;

0; 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1668.0 ;;;;;; ;;;;;;;;;;;;;;;;;;;

0; 0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 1672.0 ;;;;; ;;;;;;;;;;;;;;;;;;;

0; 0 ;;;;;;;;;;;;;;;;;; 0.0 ;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;

0; 0 ;;;;;;;;;;;;;;;;;;; 74.0 ;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;

1; 1 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;; 0.0 ;;;;;;;;;;;;

1; 1; 0.0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;

3; 3; 4.0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;

3; 3 ;;;;;;;;;;;;;;;;;;;;;;;;; 75.0 ;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;

5; 5; 0.0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;

5; 5 ;;;;;;;;;;;;;;;;;;;;;;;;; 85.0 ;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;

现在,我需要一种方法将具有相同第一列名称的所有行连接到一列中,例如:

INT; INT2; STRING; STRING; STRING; STRING; STRING; STRING; STRING; STRING; STRING; and_so_on ......

0; 0 ;;;;;;;;;;;;; 30.0 ;;;;; 0.0; 74.0 ;;;;;;;;;;;;;;;; 1668.0; 1672.0 ;;; 160.0 ;;;;; 0.0; 0.0 ;;;;;;;;;;;;;; - 1.0; 0; 0; 1; -1.0

1; 1; 0.0 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;; 0.0 ;;;;;;;;;;;;

3; 3; 4.0 ;;;;;;;;;;;;;;;;;;;;;;;; 75.0 ;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;

5; 5; 0.0 ;;;;;;;;;;;;;;;;;;;;;;;; 85.0 ;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;

它是相同数量的colums(即使“resultrow”0; 0 ....可能有太多“;”因为我伪造它;-) 数字只在同一个indexrow中出现一次,所以它有点“合并同一个indexrow” 我需要读取> 20k(也可以是> 1百万行)长文件的东西。 压缩列表 并将文件再次写回磁盘。

帮助者只是向代码的方向倾斜,我无法: - /(但是...... :-) 最尊重 - 我不编码脸红 - 我可以阅读但不设计它。 我发布代码将是 - 让我们说有趣: - )

我非常赞赏这些帮助。 br //

1 个答案:

答案 0 :(得分:0)

import csv
from itertools import izip_longest

def merge_rows(a, b):
    return [x or y for x,y in izip_longest(a, b, fillvalue='')]

def main():
    data = {}

    with open("infile.csv", "rb") as inf:
        incsv = csv.reader(inf, delimiter=";")
        header = next(incsv, [])
        for row in incsv:
            label = row[0]
            try:
                data[label] = merge_rows(data[label], row)
            except KeyError:
                data[label] = row

    # write data in sorted order by label
    keys = sorted(data, key=lambda k: int(k))    # Python 2
    # keys = sorted(data.keys(), key=lambda k: int(k))    # Python 3

    with open("outfile.csv", "wb") as outf:
        outcsv = csv.writer(outf, delimiter=";")
        outcsv.writerow(header)
        outcsv.writerows(data[key] for key in keys)

if __name__=="__main__":
    main()

编辑:我根据您的示例数据制作了一些mod:

  1. 为csv读者和作者添加了delimiter=";"参数

  2. 添加了读取和写入标题的代码

  3. 添加了一个关键子句,因此排序顺序是数字,而不是词典

  4. 工作原理:

    for row in incsv:对于数据文件中的每一行,我们都会得到一个列表 - 类似于["0", "0", "", "", "", "", "", "", "", "", "", "", "-1.0", "0", "0", "-1", "0"]。然后label = row[0]为标签提供值"0" - 您想要的第一列值 - 我们会查找data[label],这是来自具有该标签的所有预先存在的行的合并行。

    如果该组合行已经存在,我们会将新行合并到其中(stored_row = merge_rows(stored_row, new_row);否则会使用新行值(["0", "0", "", "", "", "", "", ""等)创建。所以有效merge_rows除了第一次出现之外,每个标签的每次出现都会被调用。

    merge_rows获取一对列表并将它们合并 - izip_longest返回相应的条目,即izip_longest([0, 1, 2], ["a", "b", "c"])给出(0, "a"), (1, "b"), (2, "c")。如果一个列表比另一个列表短,则用fillvalue填充它以匹配它收到的最长列表的长度。 xy会为每个列表分配相应的值,我们or将它们放在一起,因为......好吧,因为or按照您想要的方式组合它们({{ 1}},'' or '1' == '1''1' or '' == '1')。然后它获取所有结果值并将它们作为列表返回 - 结果组合行。

    希望有所帮助。