【问题标题】:joining-all-rows-of-a-csv-file-that-have-the-same-1st-column-value加入所有行的 csv 文件具有相同的第一个列值
【发布时间】:2014-03-14 00:12:28
【问题描述】:

确定需要主要示例更新。

我有这个: 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;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;

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

帮助者只提示编码的方向,我无法:-/(还... :-) 怀着最大的敬意 - 我不编写代码 blush - 我可以阅读它但不会设计它。 我发布代码会 - 可以说很有趣:-)

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

【问题讨论】:

  • 刚刚意识到我在文本中有一个标题,其他行是整数或文本。
  • 你试过什么?如果您发布您拥有的代码,它会更容易为您提供帮助。
  • 您可能需要解释“连接两行”的概念。对许多人来说,这意味着一个接一个地附加,但你似乎意味着不同的东西......更像是“对于每个字段,从两个选项中选择'最佳'值”,但那是什么“最超值?您想如何处理冲突?
  • 做了一个重要的示例更新以试图澄清。我不想追加。我希望正如您所说的@twalberg 从同一索引行的不同行中选择值,并创建一个唯一的索引行,其中所有值都来自该索引。冲突“不应该”存在,但平均值会很好:-)

标签: python csv merge


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

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

  1. 向 csv 读取器和写入器添加了 delimiter=";" 参数

  2. 添加了读写头的代码

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

它是如何工作的:

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 接受一对列表并将它们组合起来——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',@987654342 @)。然后它获取所有结果值并将它们作为列表返回 - 结果组合行。

希望对您有所帮助。

【讨论】:

  • 这个答案只是对没有合并它们的行进行排序,就好像它一直在发生 keyerror 一样。它还把标题放在底部。谢谢你的帖子。 //
  • 我没有得到这个奇迹行返回 [x or y for x,y in izip_longest(a, b, fillvalue='')]
  • 我没有得到这个奇迹行 return [x or y for x,y in izip_longest(a, b, fillvalue='')] /对不起,我无法理解它。显然它从未使用过。
猜你喜欢
  • 2012-06-17
  • 2017-06-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多