【问题标题】:writing "dictionary of dictionaries" to .csv file in a particular format以特定格式将“字典中的字典”写入 .csv 文件
【发布时间】:2015-10-04 20:53:21
【问题描述】:

我正在从多个 .csv 文件中生成一个字典,它看起来像这样(示例):

dtDict = {'AV-IM-1-13991730': {'6/1/2014 0:10': '0.96',
                      '6/1/2014 0:15': '0.92',
                      '6/1/2014 0:20': '0.97'},
 'AV-IM-1-13991731': {'6/1/2014 0:10': '1.96',
                      '6/1/2014 0:15': '1.92',
                      '6/1/2014 0:20': '1.97'},
 'AV-IM-1-13991732': {'6/1/2014 0:10': '2.96',
                      '6/1/2014 0:15': '2.92',
                      '6/1/2014 0:20': '2.97'},
 'AV-IM-1-13991733': {'6/1/2014 0:10': '3.96',
                      '6/1/2014 0:15': '3.96',
                      '6/1/2014 0:20': '3.97'}}

我想将其保存为以下格式的 .csv 文件:

timestamp,AV-IM-1-13991730,AV-IM-1-13991731,AV-IM-1-13991732,AV-IM-1-13991733
6/1/2014 0:10,0.96,1.96,2.96,3.96
6/1/2014 0:15,0.92,1.92,2.92,3.96
6/1/2014 0:20,0.97,1.97,2.97,3.97

我现在拥有的一段代码(与这个目标相关):

header = '''# file...... Recorder file
# date...... Thu Mar 12 14:35:32 2015
# user...... Sri
# host...... (null)
# group..... None
# property.. AVA Measurements
# limit..... 
# interval..''' 

testpower        = open("custpower.csv",'w')
testpower.writelines([header,'\n','# timestamp\n'])
...
for key, value in dtDict.iteritems():
    #Still trying to figure out how to write to custpower.csv

我尝试做类似的事情:

for key, value in dtDict.iteritems():
    testpower.writelines([key,',',','.join(value),'\n'])

但它并没有完全做到我想要做的。

【问题讨论】:

    标签: python csv dictionary


    【解决方案1】:

    试试这个:

    outStr = ''
    for key, value in dtDict.iteritems():
        outStr += str(key) + ','
    
    outStr = outStr[:-1]
    print outStr
    
    valueStr1 = '6/1/2014 0:10'
    valueStr2 = '6/1/2014 0:15'
    valueStr3 = '6/1/2014 0:20'
    
    for keys, values in dtDict.iteritems():
        for key, value in values.iteritems():
            if key == '6/1/2014 0:10':
                valueStr1 += str(value)
            if key == '6/1/2014 0:15':
                valueStr2 += str(value)
            if key == '6/1/2014 0:20':
                valueStr3 += str(value)
    
    print valueStr1
    print valueStr2
    print valueStr3
    

    当然不是print,而是写入文件。

    编辑:考虑到下面的混乱

    【讨论】:

    • 它不工作。打印输出看起来像(用 , 替换 +):AV-IM-1-13991730,AV-IM-1-13991731,AV-IM-1-13991732,AV-IM-1-13991733 ('6/1/2014 0:10', '0.96') ('6/1/2014 0:20', '0.97') ('6/1/2014 0:15', '0.92') ('6/1/2014 0:10', '1.96') ('6/1/2014 0:20', '1.97') ('6/1/2014 0:15', '1.92') ('6/1/2014 0:10', '2.96') ('6/1/2014 0:20', '2.97') ('6/1/2014 0:15', '2.92') ('6/1/2014 0:10', '3.96') ('6/1/2014 0:20', '3.97') ('6/1/2014 0:15', '3.97')
    • strange 在我的电脑上工作正常,可能会在写入文件时添加'\n' 转义字符。我将编辑我的答案。
    • 您的代码正在做的是创建时间的多个实例(就像我在上面的评论中粘贴的那样)但是 .csv 中的输出应该看起来像我在问题中显示的示例输出,即只有应该创建一个时间戳,并且应该将值附加在用逗号分隔的同一行中(如我的问题所示)。
    • 不确定你在我的代码中得到了什么给我以下输出,AV-IM-1-13991730,AV-IM-1-13991731,AV-IM-1-13991732,AV-IM-1-13991733 6/1/2014 0:100.96 6/1/2014 0:200.97 6/1/2014 0:150.92 6/1/2014 0:101.96 6/1/2014 0:201.97 6/1/2014 0:151.92 6/1/2014 0:102.96 6/1/2014 0:202.97 6/1/2014 0:152.92 6/1/2014 0:103.96 6/1/2014 0:203.97 6/1/2014 0:153.96
    • 它不会以这种格式显示,但它与您在原始帖子中发布的格式相同。
    【解决方案2】:

    您可以像这样将数据重新组织到一个新的列表结构字典中。请记住,这将在打印之前读取整个文件(它必须获取第一个时间戳的最后一个值)。因此,如果您的输入很大,它可能会很慢。此外,字典不会按任何特定顺序保存它们的键,因此如果顺序很重要,您可能需要将键保存在单独的列表中。

    ts = dtDict.keys()
    
    print "timestamp," + ",".join(ts)   
    reformatted = {}
    
    for k in ts:
        sub_dict = dtDict[k]
        for timestamp in sub_dict.keys():
            value = sub_dict[timestamp]
            if not reformatted.has_key(timestamp):
                reformatted[timestamp] = []
            reformatted[timestamp].append(value)
    
    for rec in reformatted.keys():
        print rec + " " + ",".join(reformatted[rec])
    

    当然,如果时间戳的集合总是一致的,你可以做一些更简单的事情:

    datasets = dtDict.keys()
    timestamps = dtDict[datasets[0]].keys()
    
    
    for ts in timestamps:
        values = []
        for ds in datasets:
            values.append(dtDict[ds][ts])
        print ts + " " + "".join(values)
    

    同样,除非您提前设置顺序,否则它将以任意顺序显示。因此,无需从字典本身设置时间戳,您只需提前阅读它们即可。

    【讨论】:

    • 时间步长和时间戳是一致的。在我实现您的代码以写入 .csv 文件之前,如何按时间升序对字典进行排序?
    • 字典不能按顺序存储东西,但你可以保留一个单独的键列表:dtDict = {"6:15" : "0.9", "6:10" : "0.8", 6:20" : "0.2"}timestamps_in_order = ["6:10", "6:15","6:20"] 然后,而不是循环通过data.keys()循环通过timestamps_in_order和引用键的数据。如何制作时间戳列表取决于您的输入。你可能可以逃脱惩罚:timestamps_in_order = dtDict[datasets[0]].keys()timestamps_in_order.sort()
    【解决方案3】:

    要浏览您的 AV-IM-1-139917XX 代码和日期,字典词典有点麻烦。由于当我们调用dtDict.iteritems() 之类的东西时我们无法保证顺序,我们需要将键作为列表获取并对其进行排序。我使用 ID (AV-IM-1-139917XX) 和日期列表来执行此操作。

    这就是我想出的。它可能很难看,但它有效:

    编辑:将sorted添加到dtDict.keys()

    dates = []
    av_im = sorted(dtDict.keys())
    
    for k, v in dtDict.iteritems():
        dates = v.keys()  # this returns a list of date keys
    
    dates = sorted(list(set(dates)))  # remove duplicates and sort
    print dates  # ['6/1/2014 0:10', '6/1/2014 0:15', '6/1/2014 0:20']
    print av_im  # ['AV-IM-1-13991730', 'AV-IM-1-13991731', 'AV-IM-1-13991732', 'AV-IM-1-13991733']
    

    这会得到我需要在您的字典中导航的值列表。所以现在我可以这样做了:

    csv_list = []
    for date in dates:
        s = str(date)
        for code in av_im:
            s = s +','+str(dtDict[code][date])
        csv_list.append(s)
    
    print csv_list  # ['6/1/2014 0:10,0.96,1.96,2.96,3.96', '6/1/2014 0:15,0.92,1.92,2.92,3.96', '6/1/2014 0:20,0.97,1.97,2.97,3.97']
    

    现在我们可以写入 csv:

    import csv
    with open('mycsv.csv', 'w') as f:
        w = csv.writer(f, delimiter = ',')
        w.writerows([s.split(',') for s in csv_list])
    

    我们得到一个如下所示的 csv:

    6/1/2014 0:10,0.96,1.96,2.96,3.96
    6/1/2014 0:15,0.92,1.92,2.92,3.96
    6/1/2014 0:20,0.97,1.97,2.97,3.97
    

    根据需要自定义以包含您的标题...

    需要考虑的一些事项:在示例中,您给出的日期/时间很容易排序。如果您的真实数据集跨越多天或使用 12 小时制或其他比您显示的更复杂的东西,那么您应该将日期/时间的唯一列表转换为 datetime 对象列表并对它们进行排序。

    【讨论】:

      【解决方案4】:

      如果您可以使用pandas,这将非常简单。

      import pandas as pd
      
      data = {'AV-IM-1-13991730': {'6/1/2014 0:10': '0.96',
                                   '6/1/2014 0:15': '0.92',
                                   '6/1/2014 0:20': '0.97'},
              'AV-IM-1-13991731': {'6/1/2014 0:10': '1.96',
                                   '6/1/2014 0:15': '1.92',
                                   '6/1/2014 0:20': '1.97'},
              'AV-IM-1-13991732': {'6/1/2014 0:10': '2.96',
                                   '6/1/2014 0:15': '2.92',
                                   '6/1/2014 0:20': '2.97'},
              'AV-IM-1-13991733': {'6/1/2014 0:10': '3.96',
                                   '6/1/2014 0:15': '3.96',
                                   '6/1/2014 0:20': '3.97'}}
      
      df = pd.DataFrame(data)
      df.to_csv(PATH_TO_OUTPUT_FILE)
      

      df 变成了一个 DataFrame,看起来像

                    AV-IM-1-13991730 AV-IM-1-13991731 AV-IM-1-13991732 AV-IM-1-13991733
      6/1/2014 0:10             0.96             1.96             2.96             3.96
      6/1/2014 0:15             0.92             1.92             2.92             3.96
      6/1/2014 0:20             0.97             1.97             2.97             3.97
      

      你生成的 csv 看起来像

      ,AV-IM-1-13991730,AV-IM-1-13991731,AV-IM-1-13991732,AV-IM-1-13991733
      6/1/2014 0:10,0.96,1.96,2.96,3.96
      6/1/2014 0:15,0.92,1.92,2.92,3.96
      6/1/2014 0:20,0.97,1.97,2.97,3.97
      

      Pandas 也不错,因为你可以这样做:

      df.convert_objects(convert_numeric=True).plot()
      # the converts change "0.97" -> 0.97 so it's plottable
      

      获得:

      【讨论】:

      • 这非常简单。我需要阅读 DataFrame 我将在整个文件 (550MB) 上尝试此代码并进行测试
      • 与我的回答相比,这非常简单。
      • @Scott 我尝试制作一个像[(timestamp, header, value) for header, d in data.items() for timestamp, value in d.items()] 这样的数据点列表并从那里开始,但我无法做出任何不比罪恶更丑陋的工作。最终我想“我想知道我是否足够了解 pandas 以将数据转移到这里需要的地方。”结果这一切都到了它应该去的地方——我很幸运!
      • 是的,我正在尝试一些巧妙的解包和 itertools.groupby,但无法提出任何建议。很高兴看到熊猫可以轻松做到这一点。
      • 貌似pandas也是自动排序的还是列和行排序只是巧合?
      猜你喜欢
      • 1970-01-01
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-04
      • 2020-10-17
      • 1970-01-01
      相关资源
      最近更新 更多