首页 > 解决方案 > 格式化数据点列表以显示在图表中

问题描述

我正在 Django Rest Framework 中编写 API 端点,并希望为图形格式化数据。我有这样的数据,我从数据库中获得:

data = [
    {
        "name": "Test 3",
        "status": "Active",
        "count": 1
    },
    {
        "name": "Test 2",
        "status": "Failed",
        "count": 1
    },
    {
        "name": "Test",
        "status": "In Progress",
        "count": 85
    },
    {
        "name": "Test",
        "status": "Failed",
        "count": 40
    },
    {
        "name": "Test",
        "status": "Active",
        "count": 1
    },
    {
        "name": "Test",
        "status": "Success",
        "count": 218
    },
    {
        "name": "Test 2",
        "status": "Active",
        "count": 1
    }
]

我想像这样格式化上面的最终图形数据,以便在图形中显示它:

[
    "labels": ['Test', 'Test 2', 'Test 3'],
    "data": [
        {
            name: 'Active',
            data: [1, 1, 1]
        },
        {
            name: 'Failed',
            data: [40, 1, 0]
        },
        {
            name: 'Success',
            data: [218, 0, 0]
        },
        {
            name: 'In Progress',
            data: [85, 0, 0]
        }
    ]
]

我正在尝试以这种方式格式化数据,但我无法这样做。是否有任何内置函数可用于使数据格式正确?

response = [
    {
        'labels': [],
        'data': [],
    }
]
for row in data:
    if row['name'] not in response[0]['labels']:
        response[0]['labels'].append(row['name'])
        innerData = []
        for status in ['Active', 'Failed', 'Success', 'In Progress']:
            if status in row['status']:
                innerData.append(row['count'])
            else:
                innerData.append(0)
        response[0]['data'].append(
            {
                'name': status,
                'data': innerData,
            }
        )

标签: pythondjangodata-structures

解决方案


基于 Rustam 的回答:

  1. Add a dictionary label_to_idx to be used to determine the index by label.
  2. Pass a lambda function to defaultdict to initialize lists of correct size and default value.
  3. Populate d for each status, using label_to_idx to find the correct index to fill with count.
from collections import defaultdict

data = [
    {"name": "Test 3", "status": "Active",      "count": 1},
    {"name": "Test 2", "status": "Failed",      "count": 1},
    {"name": "Test",   "status": "In Progress", "count": 85},
    {"name": "Test",   "status": "Failed",      "count": 40},
    {"name": "Test",   "status": "Active",      "count": 1},
    {"name": "Test",   "status": "Success",     "count": 218},
    {"name": "Test 2", "status": "Active",      "count": 1},
]

labels = sorted({each['name'] for each in data})
label_to_idx = {label: idx for idx, label in enumerate(labels)}    # Added
d = defaultdict(lambda: [0] * len(labels))                         # Modified

for each in data:
    d[each['status']][label_to_idx[each['name']]] = each['count']  # Modified

final_result = {'labels': labels, 'data': []}
for k, v in d.items():
    final_result['data'].append({'name': k, 'data': v})
from pprint import pprint as pp

pp(final_result)
# {'data': [{'data': [1, 1, 1], 'name': 'Active'},
#           {'data': [40, 1, 0], 'name': 'Failed'},
#           {'data': [85, 0, 0], 'name': 'In Progress'},
#           {'data': [218, 0, 0], 'name': 'Success'}],
#  'labels': ['Test', 'Test 2', 'Test 3']}

推荐阅读