You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Google Charts实现Ruby分组数组数据的动态折线图

我来帮你梳理下怎么把Ruby分组的数据转换成Google Charts需要的格式,毕竟Google Charts和Highcharts的数据结构确实不太一样,得先把数据规整成它能识别的结构才行。

先明确Ruby传来的数据结构

首先咱们得先对齐数据格式,假设你从Ruby端输出并传给前端的JSON解析后是这样的结构(我模拟了一组示例数据):

// 前端解析后的Ruby分组数据
const rubyGroupedData = [
  ["Product A", "Product B"], // 第一个元素:产品名称数组
  [
    ["2024-01-01", 100], ["2024-01-02", 150], // Product A的日期+成本数据
    ["2024-01-01", 80], ["2024-01-02", 120]   // Product B的日期+成本数据
  ]
];

这里默认第二个数组里,每个产品的日期成本数据是连续排列的(比如先放完Product A的所有数据,再放Product B的),如果你的数据不是这个顺序,后面我会补充调整方法。


方法一:手动构建DataTable(灵活适配各种数据情况)

如果你的数据存在日期不统一、部分产品某日期无数据的情况,用这个方法更稳妥:

// 1. 提取基础数据
const productNames = rubyGroupedData[0];
const rawDataPoints = rubyGroupedData[1];

// 2. 按产品拆分原始数据
const pointsPerProduct = rawDataPoints.length / productNames.length;
const productData = productNames.map((name, index) => {
  // 计算当前产品数据的起止索引
  const startIdx = index * pointsPerProduct;
  const endIdx = startIdx + pointsPerProduct;
  return {
    name: name,
    data: rawDataPoints.slice(startIdx, endIdx).map(point => ({
      date: new Date(point[0]), // 转成Google Charts要求的Date对象
      cost: point[1]
    }))
  };
});

// 3. 收集所有唯一日期并排序
const allDates = [...new Set(productData.flatMap(p => p.data.map(d => d.date.toISOString())))]
  .map(str => new Date(str))
  .sort((a, b) => a - b); // 按时间顺序排序

// 4. 构建DataTable
const dataTable = new google.visualization.DataTable();
// 添加X轴的日期列
dataTable.addColumn('date', 'Date');
// 为每个产品添加Y轴成本列
productNames.forEach(name => dataTable.addColumn('number', name));

// 5. 填充每一行数据(按日期匹配各产品的成本)
allDates.forEach(date => {
  const row = [date];
  productData.forEach(product => {
    // 找到当前产品在该日期的成本,无数据则设为null(折线图会自动跳过)
    const match = product.data.find(d => d.date.toISOString() === date.toISOString());
    row.push(match ? match.cost : null);
  });
  dataTable.addRow(row);
});

方法二:用ArrayDataTable(适合规整数据)

如果你的数据非常规整——每个产品的日期完全一致、顺序也相同,那可以用更简洁的arrayToDataTable方法:

// 1. 提取基础数据
const productNames = rubyGroupedData[0];
const rawDataPoints = rubyGroupedData[1];

// 2. 按产品拆分数据
const pointsPerProduct = rawDataPoints.length / productNames.length;
const productDataArrays = productNames.map((_, index) => {
  const startIdx = index * pointsPerProduct;
  return rawDataPoints.slice(startIdx, startIdx + pointsPerProduct);
});

// 3. 构造ArrayDataTable需要的二维数组
// 表头:[日期列, 产品1列, 产品2列...]
const headers = [['date', 'Date'], ...productNames.map(name => ['number', name])];
// 行数据:按日期分组,每行对应一个日期下所有产品的成本
const rows = [];
for (let i = 0; i < pointsPerProduct; i++) {
  const date = new Date(productDataArrays[0][i][0]);
  const row = [date];
  productDataArrays.forEach(product => row.push(product[i][1]));
  rows.push(row);
}

// 4. 创建ArrayDataTable
const dataTable = google.visualization.arrayToDataTable([headers, ...rows]);

最后绘制折线图

不管用哪种方法得到dataTable,绘制折线图的代码都是通用的:

// 先加载Google Charts库(记得放在HTML的<head>里)
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(drawChart);

function drawChart() {
  // 上面的代码生成dataTable...

  const options = {
    title: '产品成本趋势',
    hAxis: {title: '日期', format: 'yyyy-MM-dd'},
    vAxis: {title: '成本'},
    // 可以自定义每个产品系列的样式
    series: productNames.map((name, idx) => ({
      name: name,
      color: ['#2196F3', '#F44336'][idx]
    })),
    legend: {position: 'bottom'}
  };

  // 渲染图表到指定DOM元素
  const chart = new google.visualization.LineChart(document.getElementById('chart_div'));
  chart.draw(dataTable, options);
}

特殊情况处理:数据混排的情况

如果Ruby传来的第二个数组是按日期混排的(比如先放所有产品1号的数据,再放所有产品2号的数据),那可以用Map来重新整理数据:

const dataMap = new Map();
rawDataPoints.forEach((point, idx) => {
  const productIdx = idx % productNames.length;
  const productName = productNames[productIdx];
  const date = new Date(point[0]);
  const cost = point[1];
  
  if (!dataMap.has(date)) dataMap.set(date, new Map());
  dataMap.get(date).set(productName, cost);
});

// 之后再把dataMap转成DataTable的行数据即可,逻辑和方法一类似

内容的提问来源于stack exchange,提问作者yash041

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:08:17