【问题标题】:Python- Arranging different rows of CSV file by constant column headerPython-通过常量列标题排列不同行的CSV文件
【发布时间】:2018-10-13 08:58:31
【问题描述】:

我有一个 CSV 文件,它按以下顺序自动更新一些数据

A,B,C,D,E,F
4,2,6,4,8,9
D,C,A,B,E,F
6,4,5,8,6,2
E,F,A,C,D
4,2,7,6,5

您会注意到,标题值以不同的顺序出现在不同的行中。有时,标题列值之一也会丢失。

要求是使用一致的标题和低于该标题的所有值对其进行排序。例如

A,B,C,D,E,F
4,2,6,4,8,9
A,B,C,D,E,F
5,8,4,6,6,2
A,B,C,D,E,F
7, ,6,5,4,2

    A,B,C,D,E,F
    4,2,6,4,8,9
    5,8,4,6,6,2
    7, ,6,5,4,2

我尝试使用以下代码对其进行排序,但是它仅对第一行进行排序,然后按原样打印。

with open('mycsv.csv', 'r') as infile, open('reordered.csv', 'a') as outfile:
    fieldnames = ['A','B','C','D','E','F','G']
    writer = csv.DictWriter(outfile, fieldnames=fieldnames)
    writer.writeheader()
    for row in csv.DictReader(infile):
        writer.writerow(row)

任何关于如何实现这一点的指示都会有所帮助。谢谢。

【问题讨论】:

    标签: python python-2.7 csv


    【解决方案1】:

    我提出了一个解决方案,标题可以在任何 顺序。

    值被存储到字典中,我们希望有一个计数 到目前为止看到的(几条)线

    d = {}
    count = 0
    

    我们在几行上都有一个循环(它是 grouper 来自itertools' recipes, 接下来我们用逗号分割这两行并创建一个包含 当前标题

    for l1, l2 in zip(*[open(datafile)]*2):
        heads = l1.rstrip().split(',')
        vals  = l2.rstrip().split(',') 
        headset = set(heads) 
    

    我们有一个循环来增加与每个字典关联的列表, 使用d.setdefault 获得正确的初始值(注意 [None]*0 是无效列表 []),如果新的标题出现在舞台上 什么时候。例如,count 是 3 我们附加到包含 3 None 的列表中, [None, None, None].

        for h, v in zip(heads, vals): 
            d.setdefault(h,([None]*count)).append(v) 
    

    在考虑了这对夫妇中存在的标题之后 行中,我们考虑了之前看到的标题, 但不在这个c.o.l.中

        for h in set(d)-headset:
            d[h].append(None) 
    

    最终我们增加计数器

        count = count+1           
    

    现在我们准备好输出了,我们对键进行排序,我们打印键 接下来,每两行打印一次,我们从列表中打印 与键关联

    keys = sorted(d.keys())
    print(','.join(keys))
    for n in range(count):
        print(','.join(' ' if d[k][n] is None else str(d[k][n]) for k in keys))
    

    大家一起

    d = {}
    count = 0
    for l1, l2 in zip(*[open(datafile)]*2):
        heads = l1.rstrip().split(',')
        vals  = l2.rstrip().split(',') 
        headset = set(heads) 
        for h, v in zip(heads, vals): 
            d.setdefault(h,([None]*count)).append(v) 
        for h in set(d)-headset:
            d[h].append(None) 
        count = count+1           
    keys = sorted(d.keys())
    print(','.join(keys))
    for n in range(count):
        print(','.join(' ' if d[k][n] is None else str(d[k][n]) for k in keys))
    

    测试一下

    $ cat dat.csv 
    A,B,C,D,E,F
    4,2,6,4,8,9
    D,C,A,B,E,F
    6,4,5,8,6,2
    E,F,A,C,D
    4,2,7,6,5
    $ cat head.py 
    d = {}
    count = 0
    
    for l1, l2 in zip(*[open('dat.csv')]*2):
        heads = l1.rstrip().split(',')
        vals  = l2.rstrip().split(',') 
        headset = set(heads) 
        for h, v in zip(heads, vals): 
            d.setdefault(h,([None]*count)).append(v) 
        for h in set(d)-headset:
            d[h].append(None) 
        count = count+1
    
    keys = sorted(d.keys())
    print(','.join(keys))
    for n in range(count):
        print(','.join(' ' if d[k][n] is None else str(d[k][n]) for k in keys))
    $ python head.py 
    A,B,C,D,E,F
    4,2,6,4,8,9
    5,8,4,6,6,2
    7, ,6,5,4,2
    $ 
    

    【讨论】:

    • 我试过这段代码,但是它在单列中显示的标题很少。
    • @Zoro99 哎呀,我已经在合成数据上测试了我的代码,没有从读取文件返回的新行...如果您愿意,可以查看我更新的代码
    【解决方案2】:

    您可以导入您的文件,然后继续读取 2 行(标题 + 数据)并为它们创建一个 dict。您将 dict 添加到包含所有数据的列表中。 你得到最大的 dict(包含最多键的那个),对它进行排序并写回所有数据。

    在缺少键的字典中,可以用空字符串替换它的值:

    创建数据文件:

    with open("t.csv","w") as f:
        f.write("""A,B,C,D,E,F
    4,2,6,4,8,9
    D,C,A,B,E,F
    6,4,5,8,6,2
    E,F,A,C,D
    4,2,7,6,5""")
    

    然后:

    # read in data as list of dicts, each dict contains 2 rows worth of data    
    data = []
    with open("t.csv") as f:
        while True:
            try:
                # get a header line and a data line
                header = next(f).strip().split(",")
                d = next(f).strip().split(",")
                # create a dict from it and append it to your data collection
                data.append( {k:v for k,v in zip(header,d)} )
    
            except StopIteration:
                print("done")
                break
    
    # get a sorted set of all keys in all dicts:
    keys = set()
    for k in data:
        keys.update(k)
    keys = sorted(keys)
    
    # write the data again
    with open("new_t.csv","w") as f:
        # write headers once
        f.write(",".join(keys))
        f.write("\n")
        for d in data:
            f.write(",".join( ( d.get(k,"") for k in keys  )))
            f.write("\n")
    
    # check:
    with open("new_t.csv","r") as f:
        print(f.read())
    

    结果文件:

    A,B,C,D,E,F
    4,2,6,4,8,9
    5,8,4,6,6,2
    7,,6,5,4,2
    

    我使用 python3 样式打印 - 但代码在 python 2.7 和 3.x 中的工作方式相同。

    确保检查您的源文件是否包含标题+数据行且没有空行,否则您必须调整代码以省略空行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-29
      • 2019-02-14
      • 2017-04-16
      • 2018-07-03
      • 1970-01-01
      相关资源
      最近更新 更多