【问题标题】:Python: Looping through a dictionary (created from JSON) to create row(s)Python:循环遍历字典(从 JSON 创建)以创建行
【发布时间】:2022-01-06 18:52:53
【问题描述】:

所以,我正在尝试通过返回 JSON 的 api 调用导入 Dynatrace 数据。我将 JSON 作为字典和列表(多个嵌套)的字典导入。

我想要做的是最终得到我以后可以用来写入 csv 的行。

我认为通过示例会更有意义。

导入 JSON 的示例(缩短了空间,但我留下了 3 个我需要的“部分”):

dtrace_results = json.loads(http_response.content)

看起来像:

{'totalCount': 41, 'nextPageKey': None, 
 'result': [{'metricId': 'builtin:service.response.time', 
             'data': [{'dimensions': ['SERVICE-039D18D190DF8EE1'], 
                       'dimensionMap': {'dt.entity.service': 'SERVICE-039D18D190DF8EE1'}, 
                       'timestamps': [1641491760000, 1641491820000, 1641491880000], 
                       'values': [733, None, 724]}, 
                      {'dimensions': ['SERVICE-CF6C91BB030BB3AC'], 
                       'dimensionMap': {'dt.entity.service': 'SERVICE-CF6C91BB030BB3AC'}, 
                       'timestamps': [1641491760000, 1641491820000, 1641491880000], 
                       'values': [60951.354609929076, 56788.070796460175, 57866.69565217391]}, 
                      {'dimensions': ['SERVICE-BF03689183860CA9'], 
                       'dimensionMap': {'dt.entity.service': 'SERVICE-BF03689183860CA9'}, 
                       'timestamps': [1641491760000, 1641491820000, 1641491880000], 
                       'values': [69, 74, 78.5]}
                     ]}]}

经过一些操作使其更接近我想要的位置:

for row in dtrace_results['result'][0]['data']:
    row.pop('dimensions')

打印上述结果:(为清楚起见添加了项目符号)

  • {'dimensionMap':{'dt.entity.service':'service-039d190d190df8ee1'},'timestamps':[1641492060000,1641492120000,1641492120000,16414141414141414141800,164114141414,33,33,14,33,143,3,3,4,33,,,, ]}
  • {'dimensionMap': {'dt.entity.service': 'SERVICE-CF6C91BB030BB3AC'}, “时间戳”:[1641492060000、1641492120000、1641492180000、 1641492240000], '值': [70568.0193548387, 64320.80487804878,55929.954545454544, 57868.15151515151]}
  • {'dimensionMap': {'dt.entity.service': 'SERVICE-BF03689183860CA9'}, 'timestamps': [1641492060000, 1641492120000, 1641492180000, 1641492240000, 101, 101, 7, 1, 7 ]}

我想从上面得到的基本上是,在这个例子中,上面每行有 4 行,就像这样(数字只是为了清楚起见,结果中不需要):

  1. SERVICE-039D18D190DF8EE1,1641492060000,无
  2. SERVICE-039D18D190DF8EE1,1641492120000,1495.3333333333333
  3. SERVICE-039D18D190DF8EE1,1641492180000,1451.5
  4. SERVICE-039D18D190DF8EE1,1641492240000,无
  5. ...后面是其他行

提前感谢您的帮助。

【问题讨论】:

    标签: json python-3.x dictionary


    【解决方案1】:

    如果您正在尝试创建以项目符号给出的列表列表,那么您就快到了。只需遍历dtrace_results['result'][0]['data'](因为它是一个字典列表)并通过zipping 3 个列表通过另一次迭代获得相关值。请注意,由于row['dimensionMap']['dt.entity.service'] 不是列表,我们必须将其设为列表。

    out = []
    for row in dtrace_results['result'][0]['data']:
        
        ts = row['timestamps']
        # we need to make 'service' a list of the same length as the other lists 
        service = [row['dimensionMap']['dt.entity.service']]*len(ts) 
        vals = row['values']
        
        for zipped in zip(service, ts, vals):
            out.append(list(zipped))
    

    输出:

    [['SERVICE-039D18D190DF8EE1', 1641491760000, 733],
     ['SERVICE-039D18D190DF8EE1', 1641491820000, None],
     ['SERVICE-039D18D190DF8EE1', 1641491880000, 724],
     ['SERVICE-CF6C91BB030BB3AC', 1641491760000, 60951.354609929076],
     ['SERVICE-CF6C91BB030BB3AC', 1641491820000, 56788.070796460175],
     ['SERVICE-CF6C91BB030BB3AC', 1641491880000, 57866.69565217391],
     ['SERVICE-BF03689183860CA9', 1641491760000, 69],
     ['SERVICE-BF03689183860CA9', 1641491820000, 74],
     ['SERVICE-BF03689183860CA9', 1641491880000, 78.5]]
    

    【讨论】:

      【解决方案2】:

      我认为使用zipcsv 可以帮助您实现目标。

      鉴于您的数据如下:

      data = {
          'totalCount': 41,
          'nextPageKey': None,
          'result': [
              {
                  'metricId': 'builtin:service.response.time',
                  'data': [
                      {
                          'dimensions': ['SERVICE-039D18D190DF8EE1'],
                          'dimensionMap': {'dt.entity.service': 'SERVICE-039D18D190DF8EE1'},
                          'timestamps': [1641491760000, 1641491820000, 1641491880000],
                          'values': [733, None, 724]
                      },
                      {
                          'dimensions': ['SERVICE-CF6C91BB030BB3AC'],
                          'dimensionMap': {'dt.entity.service': 'SERVICE-CF6C91BB030BB3AC'},
                          'timestamps': [1641491760000, 1641491820000, 1641491880000],
                          'values': [60951.354609929076, 56788.070796460175, 57866.69565217391]
                      },
                      {
                          'dimensions': ['SERVICE-BF03689183860CA9'],
                          'dimensionMap': {'dt.entity.service': 'SERVICE-BF03689183860CA9'},
                          'timestamps': [1641491760000, 1641491820000, 1641491880000],
                          'values': [69, 74, 78.5]
                      },
                      ## many more
                  ]
              }
          ]
      }
      

      我们可以试试:

      results = []
      for item in data["result"][0]["data"]:
          dimension = item["dimensions"][0]
          for timestamp, value in zip(item["timestamps"], item["values"]):
              results.append({
                  "ID": dimension,
                  "timestamp": timestamp,
                  "value": value if value else "None"
              })
      

      这将允许我们这样做:

      print(results)
      

      给予:

      [
          {'ID': 'SERVICE-039D18D190DF8EE1', 'timestamp': 1641491760000, 'value': 733},
          {'ID': 'SERVICE-039D18D190DF8EE1', 'timestamp': 1641491820000, 'value': 'None'},
          {'ID': 'SERVICE-039D18D190DF8EE1', 'timestamp': 1641491880000, 'value': 724},
          {'ID': 'SERVICE-CF6C91BB030BB3AC', 'timestamp': 1641491760000, 'value': 60951.354609929076},
          {'ID': 'SERVICE-CF6C91BB030BB3AC', 'timestamp': 1641491820000, 'value': 56788.070796460175},
          {'ID': 'SERVICE-CF6C91BB030BB3AC', 'timestamp': 1641491880000, 'value': 57866.69565217391},
          {'ID': 'SERVICE-BF03689183860CA9', 'timestamp': 1641491760000, 'value': 69},
          {'ID': 'SERVICE-BF03689183860CA9', 'timestamp': 1641491820000, 'value': 74},
          {'ID': 'SERVICE-BF03689183860CA9', 'timestamp': 1641491880000, 'value': 78.5}
      ]
      

      results 转换为 csv 就很简单了。

      import csv
      with open("results.csv", "w", encoding="utf-8", newline="") as file_out:
          writer = csv.DictWriter(file_out, fieldnames=results[0].keys())
          writer.writeheader()
          writer.writerows(results)
      

      给出一个看起来像这样的 csv:

      ID,timestamp,value
      SERVICE-039D18D190DF8EE1,1641491760000,733
      SERVICE-039D18D190DF8EE1,1641491820000,None
      SERVICE-039D18D190DF8EE1,1641491880000,724
      SERVICE-CF6C91BB030BB3AC,1641491760000,60951.354609929076
      SERVICE-CF6C91BB030BB3AC,1641491820000,56788.070796460175
      SERVICE-CF6C91BB030BB3AC,1641491880000,57866.69565217391
      SERVICE-BF03689183860CA9,1641491760000,69
      SERVICE-BF03689183860CA9,1641491820000,74
      SERVICE-BF03689183860CA9,1641491880000,78.5
      

      【讨论】:

      • 谢谢,这非常接近,但我可能没有完全解释正确。应该只有一个值:每个服务的每个时间戳。我确实从你的帖子中学到了东西,所以再次感谢!
      • 抱歉,如果每个 timestamp 都与相应的 value 配对,那么您需要 zip 而不是 itertools.product()。我会更新
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-12-16
      • 2016-01-11
      • 1970-01-01
      • 2017-05-07
      • 2018-12-04
      • 2015-04-22
      • 1970-01-01
      相关资源
      最近更新 更多