首页 > 其他分享 >图表数据转化

图表数据转化

时间:2023-11-23 15:45:45浏览次数:22  
标签:转化 return data List param 图表 new 数据

图表数据转化

目标:

现在前端所需的图标数据格式大致统一,后端从数据库查询后的数据种类多种多样,希望可以通过常见的转化方法转为工具类,提高业务开发效率。

常见的数据表格式说明

下面是常见前端框架(Vue、React)中使用的图表数据格式的总结:

Vue

Vue Chart.js

  • Line Chart:

    • 数据格式:
      • labels:标签数组,表示 x 轴上的数据点。
      • datasets:数据集数组,每个数据集包含以下属性:
        • label:数据集的标签。
        • data:数据点数组,表示 y 轴上的数据。
        • borderColor:线条颜色。
        • fill:是否填充面积。
    • 示例代码:
    data() {
      return {
        chartData: {
          labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
          datasets: [
            {
              label: 'Data 1',
              data: [65, 59, 80, 81, 56, 55, 40],
              borderColor: 'red',
              fill: false
            },
            {
              label: 'Data 2',
              data: [28, 48, 40, 19, 86, 27, 90],
              borderColor: 'blue',
              fill: false
            }
          ]
        }
      }
    }
    
  • Bar Chart:

    • 数据格式:
      • labels:标签数组,表示 x 轴上的数据点。
      • datasets:数据集数组,每个数据集包含以下属性:
        • label:数据集的标签。
        • data:数据点数组,表示 y 轴上的数据。
        • backgroundColor:柱状图的填充颜色。
    • 示例代码:
    data() {
      return {
        chartData: {
          labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
          datasets: [
            {
              label: 'Data 1',
              data: [12, 19, 3, 5, 2, 3],
              backgroundColor: 'red'
            },
            {
              label: 'Data 2',
              data: [15, 9, 7, 8, 5, 7],
              backgroundColor: 'blue'
            }
          ]
        }
      }
    }
    

Vue ECharts

  • Line Chart:

    • 数据格式:
      • xAxis:x 轴配置,包含以下属性:
        • type:x 轴类型(例如 category)。
        • data:标签数组,表示 x 轴上的数据点。
      • yAxis:y 轴配置,包含以下属性:
        • type:y 轴类型。
      • series:系列数组,每个系列包含以下属性:
        • name:系列的名称。
        • type:图表类型(例如 line)。
        • data:数据点数组,表示 y 轴上的数据。
    • 示例代码:
    data() {
      return {
        chartData: {
          xAxis: {
            type: 'category',
            data: ['January', 'February', 'March', 'April', 'May', 'June', 'July']
          },
          yAxis: {
            type: 'value'
          },
          series: [
            {
              name: 'Data 1',
              type: 'line',
              data: [65, 59, 80, 81, 56, 55, 40]
            },
            {
              name: 'Data 2',
              type: 'line',
              data: [28, 48, 40, 19, 86, 27, 90]
            }
          ]
        }
      }
    }
    
  • Bar Chart:

    • 数据格式:
      • xAxis:x 轴配置,包含以下属性:
        • type:x 轴类型(例如 category)。
        • data:标签数组,表示 x 轴上的数据点。
      • yAxis:y 轴配置,包含以下属性:
        • type:y 轴类型。
      • series:系列数组,每个系列包含以下属性:
        • name:系列的名称。
        • type:图表类型(例如 bar)。
        • data:数据点数组,表示 y 轴上的数据。
    • 示例代码:
    data() {
      return {
        chartData: {
          xAxis: {
            type: 'category',
            data: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange']
          },
          yAxis: {
            type: 'value'
          },
          series: [
            {
              name: 'Data 1',
              type: 'bar',
              data: [12, 19, 3, 5, 2, 3]
            },
            {
              name: 'Data 2',
              type: 'bar',
              data: [15, 9, 7, 8, 5, 7]
            }
          ]
        }
      }
    }
    

React

React Chart.js

  • Line Chart:
    • 数据格式与 Vue Chart.js 中的相同。
  • Bar Chart:
    • 数据格式与 Vue Chart.js 中的相同。

React ECharts

  • Line Chart:
    • 数据格式与 Vue ECharts 中的相同。
  • Bar Chart:
    • 数据格式与 Vue ECharts 中的相同。

后端统一返回数据格式

Json展示

{
    "code": 200,
    "message": "成功",
    "data": {
        "x": [
            "January",
            "February",
            "March"
        ],
        "y": [
            {
                "name": "Data 1",
                "data": [
                    "77.34",
                    "72.65",
                    "74.18"
                ]
            },
            {
                "name": "Data 2",
                "data": [
                    "70.67",
                    "79.54",
                    "74.75"
                ]
            },
            {
                "name": "Data 3",
                "data": [
                    "74.66",
                    "75.39",
                    "74.12"
                ]
            }
        ]
    }
}

实体类封装:

x轴,y轴分组:

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

@Data
@NoArgsConstructor
public class TableListVo {

    @ApiModelProperty(value = "x轴数据")
    private List<String> x;

    @ApiModelProperty(value = "y轴数据")
    private List<TableYListVo> y;

    public TableListVo(List<String> x, List<TableYListVo> y) {
        this.x = x;
        this.y = y;
    }


}

y轴数据:

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;

@Data
@NoArgsConstructor
public class TableYListVo {


    @ApiModelProperty(value = "名称")
    private String name;

    @ApiModelProperty(value = "数据")
    private List<String> data;

    public TableYListVo(String name, List<String> data) {
        this.name = name;
        this.data = data;
    }
}

抽取常见的转化方式

1.根据查询的数据作为分组展示依据

数据库查询出的数据:

<==    Columns: average, variety, city
<==        Row: 70.67, apple, New York
<==        Row: 74.75, apple, Los Angeles"
<==        Row: 77.34, banana, New York
<==        Row: 74.18, banana, Los Angeles"
<==        Row: 72.65, banana, Chicago
<==        Row: 74.12, orange, Los Angeles"
<==        Row: 75.39, orange, Chicago
<==        Row: 79.54, apple, Chicago
<==        Row: 74.66, orange, New York

需求:现在希望将city作为x轴数据,variety作为y轴的name数据,average为y轴的data属性。达到的效果为,每个城市对应的品种数据以表格的形式展出,若average则赋值为0

效果图:

1700708114307

转化工具类:

 /**
     * 将数据列表转换为表格数据,可以排除指定的 x 字段和 y 字段
     *
     * @param dataList            数据列表
     * @param xFieldExtractor     x 字段值提取函数
     * @param yFieldExtractor     y 字段值提取函数
     * @param valueFieldExtractor 值字段值提取函数
     * @param excludedXFields     要排除的 x 字段值列表
     * @param excludedYFields     要排除的 y 字段值列表
     * @param fieldLabelProvider  字段标签提供函数
     * @param <T>                 数据类型
     * @return 表格数据对象
     */
    public static <T> TableListVo convertToTableDataWithExclusions(List<T> dataList, Function<T, String> xFieldExtractor, Function<T, String> yFieldExtractor, Function<T, String> valueFieldExtractor, List<String> excludedXFields, List<String> excludedYFields, Function<String, String> fieldLabelProvider) {
        try {
            // 创建一个数据映射的嵌套数据结构,用于存储每个字段的数据
            Map<String, Map<String, List<String>>> dataMap = dataList.stream().filter(obj -> excludedXFields == null || !excludedXFields.contains(xFieldExtractor.apply(obj))).collect(Collectors.groupingBy(obj -> xFieldExtractor.apply(obj), Collectors.groupingBy(obj -> yFieldExtractor.apply(obj), Collectors.mapping(obj -> String.valueOf(valueFieldExtractor.apply(obj)), Collectors.toList()))));

            // 提取 x 轴的标签,即 xField 的值列表
            List<String> xLabels = new ArrayList<>(dataMap.keySet());

            // 获取所有可能的 y 字段值
            List<String> allYValues = dataMap.values().stream().flatMap(yData -> yData.keySet().stream()).filter(yValue -> excludedYFields == null || !excludedYFields.contains(yValue)).distinct().collect(Collectors.toList());

            // 构建 y 轴的数据列表
            List<TableYListVo> yData = allYValues.stream().map(yValue -> {
                String mappedYValue = fieldLabelProvider != null ? fieldLabelProvider.apply(yValue) : yValue;
                List<String> yValueData = xLabels.stream().map(xLabel -> dataMap.getOrDefault(xLabel, new HashMap<>()).getOrDefault(yValue, new ArrayList<>())).flatMap(List::stream).collect(Collectors.toList());
                return new TableYListVo(mappedYValue, yValueData);
            }).collect(Collectors.toList());

            return new TableListVo(xLabels, yData);
        } catch (Exception e) {
            // 异常处理,记录日志等
            e.printStackTrace();
            return new TableListVo(new ArrayList<>(), new ArrayList<>());
        }
    }

调用:

List<TobaccoSensoryDto> resultList = tobaccoInfoMapper.selectBySensory();
        TableListVo tableListVo1 = TableUtils.convertToTableDataWithExclusions(resultList,TobaccoSensoryDto::getCity , TobaccoSensoryDto::getVariety, TobaccoSensoryDto::getAverage,
                null,CollectionUtil.newArrayList("红大","政和红大"),null);

2.根据查询的字段作为分组展示依据

数据库查询出的数据:

<==    Columns: aroma_quality, aroma_amount, impurity, mellowness, concentration, strength, irritation, aftertaste, create_year
<==        Row: 6.95, 7.18, 6.77, 6.86, 7.59, 7.23, 6.82, 6.77, 2013
<==        Row: 6.88, 7.42, 6.85, 6.88, 7.73, 6.77, 6.62, 6.73, 2014
<==        Row: 7.42, 7.65, 7.27, 7.27, 7.81, 7.35, 7.27, 7.23, 2015
<==        Row: 7.5, 7.5, 7.38, 7.46, 7.85, 7.69, 7.27, 7.38, 2016
<==        Row: 7.81, 7.92, 7.5, 7.88, 8.04, 7.81, 7.69, 7.69, 2017
<==        Row: 7.5, 7.8, 7.33, 7.3, 8.23, 7.77, 7.2, 7.27, 2018
<==        Row: 7.96, 8.11, 7.79, 7.75, 8.09, 7.96, 7.75, 7.71, 2019
<==        Row: 7.54, 7.58, 7.08, 7.33, 7.42, 7.33, 7.33, 7.08, 2020
<==        Row: 7.25, 7.83, 7.08, 7.21, 8.04, 7.38, 7.25, 7.17, 2021

需求:现在希望将create_year作为x轴数据,查询字段作为作为y轴的name数据,查询的字段值为y轴的data属性。达到的效果为,每年对应的9字段数据以表格的形式展出,若average则赋值为0

效果图:

1700709969695

转化工具类:

/**
     * 将数据列表转换为表格数据
     *
     * @param dataList           数据列表
     * @param xFieldExtractor    提取 x 字段值的函数
     * @param yFields            y 字段的列表
     * @param fieldLabelProvider 获取字段标签值的函数
     * @param <T>                数据类型
     * @return 表格数据对象
     */
    public static <T> TableListVo convertToTableData(List<T> dataList, Function<T, String> xFieldExtractor, List<String> yFields, Function<String, String> fieldLabelProvider) {
        try {
            // 创建一个数据映射的嵌套数据结构,用于存储每个字段的数据
            Map<String, Map<String, List<String>>> dataMap = new HashMap<>();

            // 初始化数据映射结构,为每个字段创建一个子映射
            yFields.forEach(yField -> dataMap.put(yField, new HashMap<>()));

            // 遍历数据列表,将数据按字段存储到数据映射中
            dataList.forEach(data -> {
                String xValue = xFieldExtractor.apply(data);

                yFields.forEach(yField -> {
                    String yValue = getField(data, yField);

                    // 将数据根据 x 值和对应的字段存储到数据映射中
                    if (yValue == null) {
                        yValue = "0"; // 将 null 值替换为 "0"
                    }
                    dataMap.get(yField).computeIfAbsent(xValue, k -> new ArrayList<>()).add(yValue);
                });
            });

            // 提取 x 轴的标签,即 xFieldExtractor 获得的值列表
            List<String> xLabels = new ArrayList<>(dataMap.get(yFields.get(0)).keySet());

            // 判断 x 字段的数据类型,并根据需要进行排序
            if (isNumeric(xLabels.get(0))) {
                xLabels.sort(Comparator.comparingDouble(Double::parseDouble));
            }

            // 构建 y 轴的数据列表
            List<TableYListVo> yData = yFields.stream().map(yField -> {
                String fieldLabel = fieldLabelProvider.apply(yField);

                // 提取每个字段对应的数据值
                List<String> yValueData = dataMap.get(yField).values().stream().flatMap(List::stream).collect(Collectors.toList());

                return new TableYListVo(fieldLabel, yValueData);
            }).collect(Collectors.toList());

            return new TableListVo(xLabels, yData);
        } catch (Exception e) {
            // 异常处理,记录日志等
            e.printStackTrace();
            return new TableListVo(new ArrayList<>(), new ArrayList<>());
        }
    }

    // 判断字符串是否为数字
    private static boolean isNumeric(String str) {
        if (str == null) {
            return false;
        }
        try {
            Double.parseDouble(str);
            return true;
        } catch (NumberFormatException e) {
            return false;
        }
    }

    /**
     * 获取对象的字段值
     *
     * @param data      数据对象
     * @param fieldName 字段名
     * @param <T>       数据类型
     * @return 字段值
     */
    private static <T> String getField(T data, String fieldName) {
        if (data == null || fieldName == null || fieldName.isEmpty()) {
            return null;
        }

        Class<?> clazz = data.getClass();

        try {
            Field field = clazz.getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(data).toString();
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }

        return null;
    }

调用:

 List<TobaccoSensoryEval> resultList = tobaccoChemicalEvalMapper.getHistorySensory(gradekey.getGrade());
            TableListVo tableListVo = TableUtils.convertToTableData(resultList, TobaccoSensoryEval::getCreateYear, CollectionUtil.newArrayList("aromaQuality", "aromaAmount"), TobaccoSensoryEvalField::getByFieldName);
            System.out.println("tableListVo = " + tableListVo);

标签:转化,return,data,List,param,图表,new,数据
From: https://www.cnblogs.com/RookieMaster/p/17851672.html

相关文章

  • Python爬虫与人工智能:如何让机器学会自动抓取网络数据
    随着互联网的发展,网络数据变得越来越丰富。许多公司和组织需要从网络上获取大量的数据进行分析和研究,这时候就需要一种有效的方式来自动化抓取网络数据。Python爬虫和人工智能是两个强大的技术,结合起来可以让机器学会自动抓取网络数据。Python爬虫是指使用Python语言编写程序,模拟浏......
  • Python构思如何采集天气数据
    天气数据对于许多应用领域都非常重要,如旅游规划、农业生产、气象预测等。使用Python爬虫可以方便地从各种天气网站上获取实时的天气数据。本文将介绍如何使用Python爬虫实战来爬取天气数据,帮助您在自己的项目中快速获取天气信息。1.确定目标网站和URL首先,我们需要确定一个可靠的天......
  • windows版本--人大金仓数据库连接报错----启动----及替换过期的授权文件
       启动服务命令:1、找到安装目录下server的bin进行cmd C:\ProgramFiles\Kingbase\ES\V8\KESRealPro\V008R006C007B0012\Server\bin2、执行命令:sys_ctl.exe-D"data的存放目录"startsys_ctl.exe-D"C:\ProgramFiles\Kingbase\ES\V8\data"start 3、去官网根......
  • 您可以尝试添加 --skip-broken 选项来解决该问题 ** 发现 2 个已存在的 RPM 数据库问
    ##提示如下**Found2pre-existingrpmdbproblem(s),‘yumcheck’outputfollows:2:postfix-2.10.1-7.el7.x86_64hasmissingrequiresoflibmysqlclient.so.18()(64bit)2:postfix-2.10.1-7.el7.x86_64hasmissingrequiresoflibmysqlclient.so.18(libmysqlclient_18)......
  • 在Vue中使用Mock.js虚拟接口数据实例详解
     在Vue项目中使用Mock.js可以方便地模拟接口数据,用于前端开发和测试。Mock.js是一个生成随机数据的库,可以帮助我们快速构建虚拟接口数据。在本文中,我将通过一个实例来详细讲解在Vue中使用Mock.js虚拟接口数据的方法。首先,我们需要创建一个Vue项目。可以使用VueCLI来快速创建......
  • 数据库备份与恢复
    生产环境中,数据的安全性是至关重要的,任何数据的丢失都可能产生严重的后果造成数据丢失的原因:程序错误、误操作(占比最大)、计算机失败、磁盘失败、物理灾难选择备份的依据是:丢失数据的代价与确保数据不丢失的代价之比数据库备份分类物理与逻辑区分物理备份:指对数据库操作系......
  • java把数据批量插入iotdb
    packagecom.xlkh.kafka;importcn.hutool.core.collection.CollectionUtil;importcom.alibaba.fastjson.JSON;importcom.alibaba.fastjson.JSONArray;importcom.google.common.collect.Lists;importcom.google.common.collect.Sets;importlombok.SneakyThrows;i......
  • Excel 实现两列数据对比不同颜色标记数据
    原始数据先效果存在的是绿色不存在的红色一目了然实现过程选中列选择条件格式新建数据存在规则绿色设置格式颜色查看效果新建数据不存在规则红色......
  • 使用Python调用API接口获取小红书笔记详情数据
    本文将详细介绍如何使用Python编程语言调用小红书API接口,以获取小红书笔记的详情数据。我们将从以下几个方面展开讨论:1)API接口简介;2)Python环境准备;3)API密钥获取;4)使用Requests库发送API请求;5)解析响应数据;6)异常处理与错误排查。一、API接口简介API(应用程序编程接口)是一种......
  • dremio 创建数据集命令
    以前dremio对于基于sql的数据集创建使用的命令是createvds<datasetname>asselect*from<source>新的调整为了 createview<datasetname>asselect*from<source>说明对于数据集的操作同时还支持其他修改命令,同时两个命令都可以使用参考资料https://docs.dremio.com/......