Search code examples
javascriptrangevega-lite

Issue graphing tan(x) when limiting it by range


Here is the initial graph when tan is added

Here is the tan when adapted for range

For this, I have been using the Vega Editor.

So I initially had the code for showing sin and cos absolutely fine, then when I tried to add tan, I understandably had some issues with scale, as the y values of tan were relatively huge when it approached the points where the function becomes undefined.

In order to tackle this, I added a range filter on the tan element, but it seems to be trying to join the points either side of when it is undefined. For some reason, this has also altered the sin line.

Here is the code I have so far:

{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"description": "Plots three functions using a generated sequence.",
"width": 300,
"height": 150,
"data": {
  "sequence": {
    "start": 0,
    "stop": 12.7,
    "step": 0.1,
    "as": "x"
  }
},
"transform": [
  {
    "calculate": "sin(datum.x)",
    "as": "sin(x)"
},
{
  "calculate": "cos(datum.x)",
  "as": "cos(x)"
},
{
  "calculate": "tan(datum.x)",
  "as": "tan(x)"
},
{
  "filter": {
    "field": "tan(x)",
    "range": [-1, 1]
  }
},
{
  "fold": [
    "sin(x)",
    "cos(x)",
    "tan(x)"
  ]
}
],
"mark": "line",
"encoding": {
  "x": {
    "type": "quantitative",
    "field": "x"
  },
  "y": {
    "field": "value",
    "type": "quantitative"
  },
  "color": {
    "field": "key",
    "type": "nominal",
    "title": null
  }
}
}

How I can I get this data to not try and join up points but it instead let the tan line rise until it is out of the range? I also have very little idea what is happening with sin line, it is fine without the addition of the tan line.

Any help is greatly appreciated.


Solution

  • To avoid drawing a line between adjacent points, you'll need to split each segment into a separate group: the detail encoding is useful for this. Unfortunately, a grouping like this will apply to all the lines affected by the encoding, so to avoid breaks in the sin(x) and cos(x) curves, you'll need to split the tangent into a separate layer.

    Here is how you might do this (open in editor):

    {
      "width": 300,
      "height": 150,
      "data": {"sequence": {"start": 0, "stop": 12.7, "step": 0.1, "as": "x"}},
      "transform": [
        {"calculate": "sin(datum.x)", "as": "sin(x)"},
        {"calculate": "cos(datum.x)", "as": "cos(x)"},
        {"calculate": "tan(datum.x)", "as": "tan(x)"},
        {"calculate": "floor(datum.x / PI - 0.5)", "as": "phase"}
      ],
      "encoding": {
        "x": {"type": "quantitative", "field": "x"},
        "y": {
          "field": "value",
          "type": "quantitative",
          "scale": {"domain": [-3, 3]}
        },
        "color": {"field": "key", "type": "nominal", "title": null}
      },
      "layer": [
        {"transform": [{"fold": ["sin(x)", "cos(x)"]}], "mark": "line"},
        {
          "transform": [{"fold": ["tan(x)"]}],
          "mark": {"type": "line", "clip": true},
          "encoding": {"detail": {"field": "phase", "type": "ordinal"}}
        }
      ]
    }
    

    enter image description here