繁体   English   中英

加入具有相同第一列值的csv文件的所有行

[英]joining-all-rows-of-a-csv-file-that-have-the-same-1st-column-value

确定主要示例需要更新。

确实有这样的想法将CSV文件中具有相同第一列值的所有行都连接到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 ;;;;;;;;;;;;;;;;;; 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 ;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;

它是相同数量的列(即使“ resultrow” 0; 0 ....可能有太多的“;”,因为我伪造了它;-)在同一索引行中数字只出现一次,所以有点像“合并同一索引行”,我需要读取大于20k(也可能大于100万)行的文件。 压缩列表并将文件再次写回到磁盘。

助手只会向哪个方向提示,而我却不能:-/(至今... :-)怀着最大的敬意-我没有脸红的代码-我可以阅读但不能设计。 我的发布代码是-可以说有趣:-)

我非常感谢您的帮助。 br //

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. 添加了delimiter=";" 给csv读者和作家的论点

  2. 添加代码以读取和写入标头

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

这个怎么运作:

for row in incsv :对于数据文件中的每一行,我们都有一个列表-类似于["0", "0", "", "", "", "", "", "", "", "", "", "", "-1.0", "0", "0", "-1", "0"] 然后label = row[0]给出label的值为"0" -您想要的第一列值-然后我们从所有已有该label的行中寻找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按您想要的方式将它们组合在一起( '' or '1' == '1''1' or '' == '1''' or '' == '' )。 然后,它将获取所有结果值,并将它们作为列表返回-结果组合行。

希望能有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM