【问题标题】:Make a nested JSON from online zipped CSV从在线压缩 CSV 制作嵌套 JSON
【发布时间】:2018-04-02 07:10:03
【问题描述】:

我对 Python 还很陌生,我需要在 Python 2.7 中使用标准库only特别 从在线压缩的 CSV 文件中制作嵌套 JSON。我已经弄清楚了访问和解压缩文件的方法,但是在解析时遇到了一些问题。基本上,我需要为每个主键创建一个包含三个高级元素的 JSON 输出:

  1. 主键(由 0、2、3 和 4 列组成)
  2. 一个字典,它是该 PK 观察值的时间序列(即:日期:观察值)
  3. 元数据字典(产品、流类型、单位,理想情况下是每个观察点质量的嵌套时间序列。

    from StringIO import StringIO 
    from urllib import urlopen 
    from zipfile
    import ZipFile from datetime 
    import datetime import itertools as it 
    import csv 
    import sys
    
    url = urlopen("https://www.jodidata.org/_resources/files/downloads/gas-data/jodi_gas_csv_beta.zip")
    myzip = ZipFile(StringIO(url.read())) 
    with myzip.open('jodi_gas_beta.csv','r' ) as myCSV:         
        #Read the data  
        reader=csv.DictReader(myCSV)
        #Sort the data by PK + Time for timeseries
        reader=sorted(reader,key=lambda row: row['REF_AREA'],row['ENERGY_PRODUCT'],row['FLOW_BREAKDOWN'],row['UNIT_MEASURE'],row['TIME_PERIOD']))
    
    #initialize dictionaries for output
    myData=[] 
    keys=[] 
    groups=[] 
    
    #limiting to first 200 rows for testing ONLY
    for k, g in it.groupby(list(it.islice(reader,200)),key=lambda row: row['REF_AREA'],row['ENERGY_PRODUCT'],row['FLOW_BREAKDOWN'],row['UNIT_MEASURE'])):
        keys.append(k)
        groups.append(list(g))
        myData.append({'MyPK': ''.join(k),  #captures the PKs
            'TimeSeries' : dict((zip(e['TIME_PERIOD'],e['OBS_VALUE']))) for e in g], #Not working properly, want a time series dictionary here
            #TODO: Dictionary of metadata here (with nested time series, if possible)})
    
    #TODO: Output as a JSON string
    

所以,结果应该是这样的:

{
    "myPK": "AENATGASEXPLNGM3",
    "TimeSeries":[
      ["2015-01", 756],
      ["2015-02", 572],
      ["2015-03", 654]
    ],
    "Metadata":{
      "Country":"AE",
      "Product":"NATGAS",
      "Flow":"EXPLNG",
      "Unit":"M3",
      "Quality:[
          ["2015-01", 3],
          ["2015-02", 3],
          ["2015-03", 3]
        ]
    }
}

【问题讨论】:

  • 如果您的代码正在构建您想要的结构,那么几乎所有这些都与minimal reproducible example 无关。只需向我们展示一个示例,说明 myData 中的内容以及您想用它做什么(您没有给我们的一件事)。另一方面,如果你的代码有问题,你必须解释这个问题是什么。 (此外,它必须实际运行到问题发生的地步——您发布的代码只会在 from zipfile 行上引发 SyntaxError。)
  • 反正你好像在stdlib中找到了csvZipFile等模块。还有一个叫json,它完全符合您的要求。
  • 我知道 JSON 库可以帮助进行最终转储格式化,但是让数据解析为正确的时间序列子组是我遇到的困难。刚刚更新以显示输出示例。
  • 好的,那你现在有什么? myData 与此有何不同?您需要实际告诉我们您的问题是什么,而不是让我们根据您代码中的TODO cmets 以及您在文本中没有说您知道该怎么做的事情来猜测。
  • 在我的数据中 #1 很好 - 但我似乎无法正确表示数据点的嵌套字典时间序列(这是三个输出中的 #2) - 它只是没有一个时间序列字典,我不确定我做错了什么(如果你运行代码,你会看到)。我还没有尝试过#3,因为它建立在正确的#2之上。

标签: python json python-2.7 csv itertools


【解决方案1】:

虽然您似乎没有为自己解决问题付出太多努力,但我认为这可以满足您的需求。它利用operator.itemgetter() 函数来简化从各种容器(例如lists 和dicts)中检索一系列不同的项目。

我还修改了代码以更紧密地遵循PEP 8 - Style Guide for Python Code

import datetime
import csv
from operator import itemgetter
import itertools as it
import json
from StringIO import StringIO
import sys
from urllib import urlopen
from zipfile import ZipFile

# Utility.
def typed_itemgetter(items, callables):
    """ Like operator.itemgetter() but also applies corresponding callable to
        each retrieved value if it's not None. Creates and returns a function.
    """
    return lambda row: [f(value) if f else value
                            for value, f in zip(itemgetter(*items)(row), callables)]

url = urlopen("https://www.jodidata.org/_resources/files/downloads/gas-data/jodi_gas_csv_beta.zip")
myzip = ZipFile(StringIO(url.read()))
with myzip.open('jodi_gas_beta.csv', 'r' ) as myCSV:
    reader = csv.DictReader(myCSV)
    primary_key = itemgetter('REF_AREA', 'ENERGY_PRODUCT', 'FLOW_BREAKDOWN', 'UNIT_MEASURE',
                             'TIME_PERIOD')
    reader = sorted(reader, key=primary_key)

# Limit to first 200 rows for TESTING.
reader = [row for row in it.islice(reader, 200)]

# Group the data by designated keys (aka "primary key").
keys, groups = [], []
keyfunc = itemgetter('REF_AREA', 'ENERGY_PRODUCT', 'FLOW_BREAKDOWN', 'UNIT_MEASURE')
for k, g in it.groupby(reader, key=keyfunc):
    keys.append(k)
    groups.append(list(g))

# Create corresponding JSON-like Python data-structure.
myData = []
for i, group in enumerate(groups):
    result = {'myPK': ''.join(keys[i]),
              'TimeSeries': [
                    typed_itemgetter(('TIME_PERIOD', 'OBS_VALUE'),
                                     (None, lambda x: int(float(x))))(row)
                        for row in group]
             }
    metadata = dict(zip(("Country", "Product", "Flow", "Unit"), keys[i]))
    metadata['Quality'] = [typed_itemgetter(
                            ('TIME_PERIOD', 'ASSESSMENT_CODE'), (None, int))(row)
                                for row in group]
    result['Metadata'] = metadata
    myData.append(result)

# Display the data to be turned into JSON.
from pprint import pprint
print('myData:')
pprint(myData)

# To create JSON format output, use something like:
import json
with open('myData.json', 'w') as fp:
    json.dump(myData, fp, indent=2)

打印输出的开始部分:

myData:
[{'Metadata': {'Country': 'AE',
               'Flow': 'EXPLNG',
               'Product': 'NATGAS',
               'Quality': [['2015-01', 3],
                           ['2015-02', 3],
                           ['2015-03', 3],
                           ['2015-04', 3],
                           ['2015-05', 3],
                           ['2015-06', 3],
                           ['2015-07', 3],
                           ['2015-08', 3],
                           ['2015-09', 3],
                           ['2015-10', 3],
                           ['2015-11', 3],
                           ['2015-12', 3],
                           ['2016-01', 3],
                           ['2016-02', 3],
                           ['2016-04', 3],
                           ['2016-05', 3]],
               'Unit': 'M3'},
  'TimeSeries': [['2015-01', 756],
                 ['2015-02', 572],
                 ['2015-03', 654],
                 ['2015-04', 431],
                 ['2015-05', 681],
                 ['2015-06', 683],
                 ['2015-07', 751],
                 ['2015-08', 716],
                 ['2015-09', 830],
                 ['2015-10', 580],
                 ['2015-11', 659],
                 ['2015-12', 659],
                 ['2016-01', 742],
                 ['2016-02', 746],
                 ['2016-04', 0],
                 ['2016-05', 0]],
  'myPK': 'AENATGASEXPLNGM3'},
 {'Metadata': {'Country': 'AE',
               'Flow': 'EXPPIP',
               'Product': 'NATGAS',
               'Quality': [['2015-01', 3],
                           ['2015-02', 3],
                           ['2015-03', 3],
                           ['2015-04', 3],
                           ['2015-05', 3],
                           ['2015-06', 3],
                           ['2015-07', 3],
                           ['2015-08', 3],
                           ['2015-09', 3],
                           ['2015-10', 3],
                           ['2015-11', 3],
                           ['2015-12', 3],
                           ['2016-01', 3],
                           ['2016-02', 3],
                           ['2016-03', 3],
                           ['2016-04', 3],
    # etc, etc...
]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-01
    • 2013-06-07
    • 2012-06-19
    • 1970-01-01
    • 2017-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多