具有双y轴Google Chart的多个基线

时间:2013-01-08 11:10:39

标签: google-visualization

我正在使用Google Visualization API作为一个简单的销售图表,其中包含两个系列,即销售数量和销售额,我将在具有两个轴的柱形图上显示。销售价值可能为负数,例如退货,但这会导致图表显示两个不同的基准。销售数量的零基线与最低销售额数字一致。以下是包含一些示例数据的代码示例:

google.load('visualization', '1.0', { 'packages': ['corechart'] });
google.setOnLoadCallback(drawSalesChart);

function drawSalesChart() {
    var dataTable = new google.visualization.DataTable();
    dataTable.addColumn('string', 'Order Source');
    dataTable.addColumn('number', 'Num Sales');
    dataTable.addColumn('number', 'Sales Value');

    dataTable.addRows([
        ['Web (Order)', 300, 31000],
        ['Call Centre (Order)', 700, 61000],
        ['Call Centre (Return)', 50, -4100],
        ['Call Centre (Exchange)', 10, 800]
    ]);

    var options = {
        title: 'Sales by Order Source',
        hAxis: { title: 'Order Source' },
        series: {
            0: { targetAxisIndex: 0 },
            1: { targetAxisIndex: 1 },
        },
        vAxes: {
            0: { title: 'Num Sales' },
            1: { title: 'Sales Value' }
        }
    };

    new google.visualization.ColumnChart(
        document.getElementById('livesales-chart-container')).draw(dataTable, options);
}

我已经浏览了API文档,因为有关于设置基线的信息,但似乎没有办法将每个vAx的零点绑定到同一点。我试过搜索Google和StackOverflow,但也有类似的问题,但我看不出有人遇到过这个问题。

我怎么能,甚至可以在两个系列中都显示零基线?

1 个答案:

答案 0 :(得分:0)

从可视化的角度来看,在彼此之上创建两个单独的图表可能要好得多,因为提供的数据在范围和解释方面都非常不同。

<!--
You are free to copy and use this sample in accordance with the terms of the
Apache license (http://www.apache.org/licenses/LICENSE-2.0.html)
-->

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <title>
      Google Visualization API Sample
    </title>
    <script type="text/javascript" src="http://www.google.com/jsapi"></script>
    <script type="text/javascript">
      google.load('visualization', '1', {packages: ['corechart']});
    </script>
    <script type="text/javascript">

      function drawSalesChart() {
        var dataTable = new google.visualization.DataTable();
        dataTable.addColumn('string', 'Order Source');
        dataTable.addColumn('number', 'Num Sales');
        dataTable.addColumn('number', 'Sales Value');

        dataTable.addRows([
          ['Web (Order)', 300, 31000],
          ['Call Centre (Order)', 700, 61000],
          ['Call Centre (Return)', 50, -4100],
          ['Call Centre (Exchange)', 10, 800]
        ]);

        var dataView1 = new google.visualization.DataView(dataTable);
        dataView1.setColumns([0,1]);

        var dataView2 = new google.visualization.DataView(dataTable);
        dataView2.setColumns([0,2]);

        var options1 = {
          title: 'Sales by Order Source',
          hAxis: { title: 'Order Source' },
          vAxis: { title: 'Num Sales' }
        };

        var options2 = {
          title: null,
          hAxis: { title: null, textPosition: 'none' },
          vAxis: { title: 'Sales Value' }
        };

        new google.visualization.ColumnChart(
          document.getElementById('chart1')).draw(dataView1, options1);
        new google.visualization.ColumnChart(
          document.getElementById('chart2')).draw(dataView2, options2);
      }

      google.setOnLoadCallback(drawSalesChart);

    </script>
  </head>
  <body style="font-family: Arial;border: 0 none;">
    <div id="chart1" style="width: 600px; height: 300px;"></div>
    <div id="chart2" style="width: 600px; height: 100px;"></div>
  </body>
</html>

当然,这需要一些漂亮的工具来使图形正确排列,并使颜色按照您的喜好工作,但这样您可以专注于您想要显示的主要数据,同时保持附近的其他信息作为参考。

如果你坚持在同一个图表上执行它们,你需要编写一个函数来计算网格线的位置(或弄清楚Google是如何做到的,但是我找不到它网络搜索)。

要确定图表上的最大/最小值应该是什么,“简单”的方法是获取最小值和最大值之间的差异,计算您将拥有的网格线数量(谷歌的默认值为5) ),向上舍入到最大数字的最接近的有效数字,并将它们用作网格线分隔符。

e.g。第一列:300​​,700,50,10

Max Value: 700
Min Value: 10
Exponent: LEN(Max)-1 = 2 = 10^2, nearest 100
Grid Lines: 5 - 1 = 4 (assuming you want the bottom value to serve as the floor at the same rounding, you need 4 more iterations to go over the top value)
Difference Between Max and Min: 690
Required Interval: 690 / 4 = 172.5
Rounded up to the nearest 100: 200

Min Value: FLOOR(Min,200) = 0
Max Value: CEILING(Max,200) = 800

Grid Line 1: 0
Grid Line 2: 200
Grid Line 3: 400
Grid Line 4: 600
Grid Line 5: 800

请注意,这与图表显示的内容相符。但是,它不适用于负值,因为数学变得有点复杂。

首先,您需要确定负值与最小值和最大值之间的总差异的比率。

e.g。鉴于您的第2列数据:31000,61000,-4100,800

Min Value: -4100
Max Value: 61000
Difference: 65100
Negative Ratio: 6.3%

因此6.3%的范围处于负数部分。给定5个网格线,这意味着一个网格线需要低于0,并且正部分只有4个网格线。由于负部分小于正部分,因此正部分将确定网格线间距。

所以现在你有4条网格线来覆盖正面部分(0 - 61000),这意味着你有3个段从0到61000。

这意味着61000/3,四舍五入到4位有效数字,或30,000。

这会使你的网格线:

-30,000
0
30,000
60,000
90,000

巧合的是,这就是你在图表中得到的结果。

现在你知道第二个系列有1个负网格线,你必须重新调整你的第一个系列以匹配第二个系列。因此,不是有5个网格线(上面的0和4),你现在有1个负网格线,1 0,然后是3以上,需要达到700.所以你取700的正值,除以3,为233.333

将其舍入到最接近的100,你得到300。

因此,您的第一个图表最大/最小值将重新调整为-300,以及900以下网格线:

-300
0
300
600
900

这将设置相同的基线。

这将解决您的问题 - 您需要做的就是将逻辑代码编写到Javascript中!如果您这样做,请告诉我们,我相信其他人也会遇到同样的问题。