在Vega中建立条形图,使用不同的颜色显示正负值

时间:2019-03-14 12:34:20

标签: bar-chart data-visualization vega

所以我需要使用Vega库来构建如下内容:

Bar chart with different colors for positive/ negative values

现在,我是超级n00b,所以请留意。

第一个解决方案:使用某种条件格式设置(例如在Excel中):如果bar值<0,则将其设为红色。如果条值> 0,将其设为绿色。我可以找到Vega-Lite的一些条件语法,这给了我希望,但是如何将语法转换为普通的Vega,我一无所知。

第二,我考虑过对范围使用某种颜色方案,例如具有阈值的方案。但是我对要使用的刻度范围类型完全感到困惑,并注意到刻度范围类型和配色方案之间存在某种关系,是的。困惑。

然后,我的同事建议:https://vega.github.io/editor/#/examples/vega-lite/layer_bar_annotations

因此在示例中,我们可以看到阈值以上的条形值具有条件格式。因此,我尝试过滤数据以获得2个子集:values_lower_than_0values_higher_than_0将它们用作标记的来源。但似乎我不知道该如何过滤。我的数据如下:

[
  { "date": "2018-12-10", "difference": 20 }, 
  { "date": "2018-10-21", "difference": -10 }
  ...
]

因此,我对其进行了变换:

...

{
      'name': 'values_lower_than_0',
      'source': 'temps',
      'transform': [{ 'type': 'filter', 'expr': 'datum.difference.Value < 0' }]
}

但是当我在标记中使用values_lower_than_0时,似乎什么也没发生。

所以,我有两个问题:

  • 这是构建此类图表的最佳方法吗? (TBH,在我看来似乎很令人费解)。
  • 如果是,那我应该如何获取这两个数据集并使用它们来获取正确的颜色?

2 个答案:

答案 0 :(得分:1)

一种更好的方法是不应用数据集上的变换。

here

为例

想法是将y2的值设置为Height的中间值。 y随后将根据值是正值还是负值进行调整,以分别低于midHeight或高于midHeight。请参考下面的rect类型标记配置。

{
  "$schema": "https://vega.github.io/schema/vega/v4.json",
  "width": 600,
  "height": 360,
  "autosize": "fit",
  "data": [
    {
      "name": "table",
      "url": "https://uat.gramener.com/vega/chart/data/pos-neg-items.json"
    }
  ],
  "scales": [
    {
      "name": "xscale",
      "type": "band",
      "domain": {
        "data": "table",
        "field": "category"
      },
      "range": "width",
      "padding": 0.2,
      "round": true
    },
    {
      "name": "yscale",
      "domain": {
        "data": "table",
        "field": "amount"
      },
      "nice": true,
      "range": "height"
    }
  ],
  "marks": [
    {
      "name": "bars",
      "type": "rect",
      "from": {
        "data": "table"
      },
      "encode": {
        "enter": {
          "x": {
            "scale": "xscale",
            "field": "category"
          },
          "width": {
            "scale": "xscale",
            "band": 1
          },
          "y": {
            "scale": "yscale",
            "field": "amount"
          },
          "y2": {
            "signal": "scale('yscale', 0)"
          },
          "fill": {
            "signal": "datum['amount'] > 0 ? '#5CB38B' : '#E6685C'"
          },
          "tooltip": {
            "signal": "datum"
          }
        }
      }
    },
    {
      "name": "item_score",
      "type": "text",
      "from": {
        "data": "table"
      },
      "encode": {
        "enter": {
          "x": {
            "scale": "xscale",
            "field": "category"
          },
          "y": {
            "scale": "yscale",
            "field": "amount"
          },
          "dy": {
            "signal": "datum['amount'] > 0 ? -4 : 14"
          },
          "dx": {
            "signal": "bandwidth('xscale')/2"
          },
          "align": {
            "value": "center"
          },
          "fill": {
            "value": "black"
          },
          "text": {
            "field": "amount"
          },
          "fontSize": {
            "value": 12
          }
        }
      }
    },
    {
      "name": "item_name",
      "type": "text",
      "from": {
        "data": "table"
      },
      "encode": {
        "enter": {
          "x": {
            "scale": "xscale",
            "field": "category"
          },
          "dx": {
            "value": 20
          },
          "dy": {
            "signal": "datum['amount'] > 0 ? height/2 + 14 : height/2 - 6"
          },
          "align": {
            "value": "center"
          },
          "fill": {
            "value": "#000000"
          },
          "text": {
            "field": "category"
          },
          "fontSize": {
            "value": 12
          }
        }
      }
    }
  ]
}

答案 1 :(得分:0)

我好累,今天我犯了愚蠢的错误!如果有人想使用上述第三种方法,那么我是正确的,我只是将错误的源名称传递给了商标。

另一句话是:您只需要为负值计算一个子集(例如values_lower_than_0)。

完成此操作后,所有条形都将带有一个名为bars的标记(如默认标记,带有绿色填充)。此标记的数据源将是默认数据。在该标记之上,您将应用第二个标记,例如negative_bars,其标记的来源将是values_lower_than_0,并用红色填充。

关于最佳方法的问题仍然存在。