[英]Joining all rows of a CSV file that have the same 1st column value in Python
[英]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:
添加了delimiter=";"
给csv读者和作家的论点
添加代码以读取和写入标头
添加了一个键子句,因此排序顺序为数字形式,而不是字典顺序
这个怎么运作:
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
它以匹配接收到的最长列表的长度。 x
和y
从每个列表中分配了对应的值,我们or
它们一起是因为...好吧,因为or
按您想要的方式将它们组合在一起( '' or '1' == '1'
, '1' or '' == '1'
, '' or '' == ''
)。 然后,它将获取所有结果值,并将它们作为列表返回-结果组合行。
希望能有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.