基于字典长度创建多个图表

2024-06-26 17:45:09 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在为一些水质传感器建立一个仪表板网站,这些传感器以JSON格式的API形式发送信息。计划是使用chart.js和django使用该数据创建实时图表。现在,我将JSON文件转换为字典,如下所示:

JSON file: 
{
  "11:00:00 AM": {
    "Temperatura": 30,
    "pH": 7.1,
    "Conductividad": 759,
    "Cloro Residual": 1.1,
    "Turbidez": 0,
    "Color": "<5",
    "pH de la Det de color": 7.12,
    "Solidos totales": 512,
    "S�lidos disueltos": 494,
    "S�lidos suspendidos totales": 0,
    "Dureza total como CaCO3": 227.24,
    "Alcalinidad como CaCO3": 227.7,
    "Cloruros": 64.02,
    "Fluoruros": 0.91,
    "Nitrogeno Amoniacal": 0,
    "Nitrogeno de nitritos": 0,
    "Nitrogeno de nitratos": 4.47,
    "Sulfatos": 37.27,
    "Sustancias activas al azul de metileno": 0,
    "Fenoles": 0,
    "Coliformes totales": 0,
    "Aluminio": 0,
    "Arsenico": 0.015,
    "Bario": 0.1784,
    "Calcio": 79.7,
    "Cadmio": 0,
    "Cromo": 0.0085,
    "Cobre": 0,
    "Fierro": 0.0327,
    "Potasio": 12.18,
    "Magnesio": 13.37,
    "Manganeso": 0,
    "Sodio": 55.75,
    "Plomo": 0,
    "Zinc": 0,
    "Mercurio": 0
  },

然后我将它们转换为字典,其中包含如下所有值:

    ['11:00:00 AM', '11:10:05 AM', '11:20:10 AM', '11:30:14 AM', '11:40:19 AM', '11:50:24 AM', '12:00:29 PM', '12:10:34 PM', '12:20:38 PM', '12:30:43 PM', '12:40:48 PM', '12:50:53 PM', '01:00:58 PM', '01:11:03 PM', '01:21:07 PM', '01:31:07 PM']
[[30, 30, 28, 29, 19, 0, 0, 29, 31, 33, 27, 29, 27, 29, 30, 30], [7.1, 7.6, 7.5, 7.4, 7.5, 5, 8.5, 7.7, 7.2, 7.4, 7.2, 7.4, 7.3, 7.7, 7.7, 7.7], [759, 899, 869, 898, 833, '0', '', 841, 862, 826, 861, 896, 857, 836, 864, 864], [1.1, 0.7, 1, 0.3, 1.1, '0', 1.5, 1, 0.6, 1, 0.6, 0.3, 0.6, 1, 1, 1], [0, 0, 0, 0, 0, '0', 5, 0, 0, 0, 0, 0, 0, 0, 0, 0], ['<5', '<5', '<5', '<5', '<5', '0', 20, '<5', '<5', '<5', '<5', '<5', '<5', '<5', '<5', '<5'], [7.12, 7.47, 7.4, 7.38, 7.42, '0', '', 7.58, 7.74, 7.53, 7.7, 7.45, 7.52, 7.55, 7.58, 7.58], [512, 598, 584, 599, 564, '0', '', 579, 576, 558, 586, 596, 593, 583, 569, 569], [494, 586, 562, 568, 530, '0', 1000, 538, 566, 550, 576, 564, 530, 558, 532, 532], [0, 0, 0, 0, 0, '0', '', 0, 0, 0, 0, 0, 0, 0, 0, 0], [227.24, 319.47, 296, 301.54, 263.56, '0', 500, 278.62, 292, 261.31, 298, 295.51, 300, 294.54, 279.54, 279.54], [227.7, 229.2, 222.1, 246.8, 213.4, '0', '', 232.6, 227.7, 224.8, 225.6, 44.2, 226.7, 225.4, 225.6, 225.6], [64.02, 112.16, 107, 111.17, 102.07, '0', 250, 93.69, 99.12, 91.32, 104.05, 106.7, 101.58, 96.16, 101.58, 101.58], [0.91, 0.9, 0.98, 0.94, 0.96, '0', 1.5, 1.07, 0.97, 1, 0.91, 0.94, 0.83, 0.88, 0.92, 0.92], [0, 0, 0, 0, 0, '0', 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, '0', 0.05, 0, 0, 0, 0, 0, 0, 0, 0, 0], [4.47, 4.21, 4.49, 4.51, 4.76, '0', 10, 4.01, 3.91, 3.96, 3.96, 4.67, 4.17, 3.94, 4.59, 4.59], [37.27, 43.75, 43.91, 43.33, 41.2, '0', 400, 43.39, 43.67, 42.1, 39.94, 46.48, 44.58, 42.52, 45.06, 45.06], [0, 0, 0, 0, 0, '0', 0.5, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, '0', 0.001, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, '0', 2, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, '0', 0.2, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0.015, 0.0128, 0.0121, 0.0137, 0.0147, '0', 0.05, 0.0147, 0.014, 0.0136, 0.0134, 0.0135, 0.0139, 0.0145, 0.0152, 0.0152], [0.1784, 0.192, 0.1893, 0.1783, 0.2004, '0', 0.7, 0.1913, 0.1741, 0.1762, 0.1716, 0.1763, 0.1749, 0.1906, 0.2021, 0.2021], [79.7, 102, 80.42, 93.63, 97.76, '0', '', 108.9, 84.7, 83.81, 82.5, 91.71, 86.72, 105.9, 103, 103], [0, 0, 0, 0, 0, '0', 0.005, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0.0085, 0.0043, 0.0049, 0.0077, 0.0088, '0', 0.05, 0.0073, 0.0065, 0.0073, 0.0063, 0.0078, 0.0066, 0.0071, 0.0097, 0.0097], [0, 0.0851, 0, 0.0075, 0, '0', 2, 0, 0.0623, 0.0071, 0.0102, 0.0112, 0.12, 0, 0, 0], [0.0327, 0, 0, 0, 0.0364, '0', 0.3, 0, 0, 0, 0, 0, 0, 0, 0.043, 0.043], [12.18, 11.9, 10.32, 11.51, 13.19, '0', '', 12.43, 10.58, 11.59, 10.28, 11.34, 10.86, 12.23, 13.27, 13.27], [13.37, 18.03, 15.31, 16.42, 17.23, '0', '', 15.85, 17.71, 14.72, 14.35, 16.03, 14.98, 15.6, 17.13, 17.13], [0, 0, 0, 0, 0, '0', 0.15, 0, 0, 0, 0, 0, 0, 0, 0, 0], [55.75, 56.45, 48.75, 54.63, 58.86, '0', 200, 52.8, 48.68, 53.42, 47.29, 53.85, 49.52, 52.47, 59.05, 59.05], [0, 0, 0, 0, 0, '0', 0.025, 0, 0, 0, 0, 0, 0, 0, 0, 0], [0, 0.0561, 0, 0, 0, '0', 5, 0, 0, 0.0394, 0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, '0', 0.001, 0, 0, 0, 0, 0, 0, 0.001, 0, 0]]

在我的视图页面中,我将所有这些信息发送到HTML中,chart.js使用这些数据创建图表

from django.http import JsonResponse
from django.shortcuts import render
from django.views.generic import View
import json

from rest_framework.views import APIView
from rest_framework.response import Response


class HomeView(View):
    def get(self, request, *args, **kwargs):
        return render(request, 'charts.html', {})


def get_data(request, *args, **kwargs):
    return JsonResponse(data)


class ChartData(APIView):
    authentication_classes = []
    permission_classes = []

    def get(self, request, format=None):
        with open("file.json") as f:
            data = json.load(f)
            labels_list = list(data)
            a = list(data.values())[0]
            filename = 'param_'
            counter1 = 1
            counter2 = 2
            parameters = {}
            for x in range(len(a.values())):
                counter1 = str(counter1)
                full_name = (filename + counter1)
                counter1 = counter2
                counter2 += 1
                full_values = []
                for i in data:
                    v = labels_list.index(i)
                    aaa = list(data.values())[v]
                    val = list(aaa.values())[x]
                    full_values.append(val)
                parameters[full_name] = full_values
        labels = list(data)
        name_param = list(a)
        data = {
            "labels": labels,
            "values": list(parameters.values()),
            "name_param": name_param,
        }
        return Response(data)

我的问题是创建图表,现在我必须手动创建画布,给它们ID,为它们和它们各自的数据创建新的上下文

{% extends 'base.html' %}

<script>
{% block jquery %}
var endpoint = '/api/chart/data/'
var labels =  []
var values = []
var name_param = []

$.ajax({
    method: "GET",
    url: endpoint,
    success: function(data){
        labels = data.labels
        values = data.values
        name_param = data.name_param
        console.log(data)
        setChart()
    },
    error: function(error_data){
        console.log("error")
        console.log(error_data)
    }
})
function setChart(){
                var ctx = document.getElementById('myChart');
                var ctx2 = document.getElementById('myChart2');
                var ctx3 = document.getElementById('myChart3');
                var ctx4 = document.getElementById('myChart4');
                var ctx5 = document.getElementById('myChart5');
                var ctx6 = document.getElementById('myChart6');
                var myChart = new Chart(ctx6, {
                    type: 'line',
                    data: {
                        labels: labels,
                        datasets: [{
                            label: name_param[5],
                            data: values[5],
                            fill: false
                        }]
                    }

                })
                var myChart = new Chart(ctx5, {
                    type: 'line',
                    data: {
                        labels: labels,
                        datasets: [{
                            label: name_param[4],
                            data: values[4],
                            fill: false
                        }]
                    }

                })
                var myChart = new Chart(ctx4, {
                    type: 'line',
                    data: {
                        labels: labels,
                        datasets: [{
                            label: name_param[3],
                            data: values[3],
                            fill: false
                        }]
                    }

                })
                var myChart = new Chart(ctx3, {
                    type: 'line',
                    data: {
                        labels: labels,
                        datasets: [{
                            label: name_param[2],
                            data: values[2],
                            fill: false
                        }]
                    }

                })
                var myChart = new Chart(ctx2, {
                    type: 'line',
                    data: {
                        labels: labels,
                        datasets: [{
                            label: name_param[1],
                            data: values[1],
                            fill: false
                        }]
                    }

                })
                var myChart = new Chart(ctx, {
                    type: 'line',
                    data: {
                        labels: labels,
                        datasets: [{
                            label: name_param[0],
                            data: values[0],
                            fill: false
                        }]
                    }

                })
}
{% endblock %}
</script>

{% block content %}

<div class='row'>
    <div class='col-sm-12' url-endpoint='{% url "api-data" %}'>
        <h1>Hello World</h1>
        <div class="col-sm-4">
        <canvas id="myChart" width="400" height="400"></canvas>
        </div>
        <div class="col-sm-4">
        <canvas id="myChart2" width="400" height="400"></canvas>
        </div>
        <div class="col-sm-4">
        <canvas id="myChart3" width="400" height="400"></canvas>
        </div>
        <div class="col-sm-4">
        <canvas id="myChart4" width="400" height="400"></canvas>
        </div>
        <div class="col-sm-4">
        <canvas id="myChart5" width="400" height="400"></canvas>
        </div>
        <div class="col-sm-4">
        <canvas id="myChart6" width="400" height="400"></canvas>
        </div>
    </div>
</div>

{% endblock content %}

我的问题是,是否有一种方法可以让for循环为每个参数创建图表。或者,您建议如何创建多个图表


Tags: namedivdatalabelsparamvarcolam
1条回答
网友
1楼 · 发布于 2024-06-26 17:45:09

在查看数据时,我认为您可以从改进数据结构开始。原因是数据是每个图表唯一不同的东西。因此,根据图表的需要调整数据是使前端更容易创建图表的一种好方法

valuesname_param列表都是独立的,但它们都通过索引链接。这可以通过在新字典中创建name_param/value组来改进。命名属性以镜像Chart实例的设置会更好,比如labeldata

尝试将列表修改为以下结构

{
  labels: [], // Labels remains unchanged.
  datasets: [ // New array with objects.
    {
      label: '', // previously known as name_param
      data: '' // previously known as value
    },
    {
      label: '',
      data: ''
    },
    // ... etc.
  ]
}

这使您能够轻松地循环dataset属性中的每个组,并为每个组创建一个新图表。但是首先需要一些帮助函数来创建<div><canvas>Chart实例

首先是<div><canvas>。下面的函数创建引导列和画布元素,它们将被放置在DOM中

function createCanvasAndColumn() {
  const column = document.createElement('div');
  div.classList.add('col-sm-4');

  const canvas = document.createElement('canvas');
  canvas.width = 400;
  canvas.height = 400;

  column.append(canvas);
 
  /** 
   * Return both the canvas and the column.
   * The column is needed to append to the row.
   * The canvas is needed to create a chart with.
   */
  return { canvas, column };
}

我们不需要id属性,因为在canvas常量中已经有了对元素的引用。画布将被附加到<div>。然后,它返回一个对象,其中包含对列的引用(需要添加到文档中)和对画布的引用(需要用于Chart实例)

现在来创建图表。我已经记住了答案开头建议的更改后的数据结构,以及数据在应用程序中的显示方式,因此下面的函数使用该结构

const chartsRow = document.getElementById('charts-row');

function createCharts({ labels, datasets }) {
  /**
   * Loop over each item in datasets and create a
   * new chart for each item. Each chart is then returned
   * resulting in an array of Chart instances.
   */
  const charts = datasets.map((dataset) => {
    const { canvas, column } = createCanvasAndColumn();

    const chart = new Chart(canvas, {
      type: 'line',
      data: {
        labels: labels,
        datasets: [{
          ...dataset,
          fill: false
        }]
      }
    });

    // Add column (and canvas) to the row.
    chartsRow.append(column);
    return chart;
  });

  /**
   * Return the charts array. This is not mandatory,
   * but it might come in handy if you'd need to access
   * the Chart instances at some point.
   */
  return charts;
}

createCharts函数需要一个具有labelsdataset键的对象。它在datasets数组上循环,为每个集合创建一个canvas元素。然后,该canvas元素将用于创建一个新的Chart实例。每个数据集的namevalue将用于设置该Chart实例的数据

您可能已经注意到循环是通过map完成的。这将在数组中的每个项上循环,并期望每个项都有一个return语句。这将导致根据循环中的返回值创建一个新数组。charts常量实际上是Chart实例的数组

现在,有了这些函数,您所要做的就是将从Django应用程序收到的数据传递到createCharts函数中以构建图表

通过添加id属性使行易于选择。此属性应具有唯一的值。在上面的createCharts代码段中,将从文档中选择元素以附加图表

<div class='row' id="charts-row">
  <div class='col-sm-12' url-endpoint='{% url "api-data" %}'>
    <h1>Hello World</h1>
  </div>
</div>

从这里调用请求并将数据传递给createCharts函数,然后该函数在数据上循环并为每个项创建一个图表

const endpoint = '/api/chart/data/';

$.ajax({
  method: "GET",
  url: endpoint,
  success: function(data) {
    createCharts(data);
  },
  error: function(jqXHR, textStatus, errorThrown) {
    console.log("error");
    console.log(textStatus);
  }
})

相关问题 更多 >