In Vega visualization, how to use a custom mark instead of just text in the word cloud?

134 views Asked by At

I'm trying to make a word cloud using Vega wordcloud, documented here https://vega.github.io/vega/docs/transforms/wordcloud/

But I'd like to show the word count below each word, and in a smaller font than the word itself.

'\n' characters are not interpreted.

Using HTML instead of text doesn't work (a <br> tag for example, is just displayed as the text "<br>").

Maybe if it was possible to insert custom SVG, I could do it, but I don't see how to use that with the word cloud.

Any help appreciated.

Here's my original code, that doesn't display the counts at all.

{
  "$schema": "https://vega.github.io/schema/vega/v5.json",
  "description": "A word cloud visualization depicting Vega research paper abstracts.",
  "width": 800,
  "height": 400,
  "padding": 0,

  "data": [
    {
      "name": "table",
      "values": [
        {"text": "apple", "weight": 15, "count": 1000},
        {"text": "banana", "weight": 20, "count": 1700},
        {"text": "orange", "weight": 20, "count": 1200}
      ],
      "transform": [
        {
          "type": "formula", "as": "angle",
          "expr": "[-45, 0, 45][~~(random() * 3)]"
        },
        {
          "type": "formula", "as": "weight",
          "expr": "if(datum.text=='VEGA', 600, 300)"
        }
      ]
    }
  ],

  "scales": [
    {
      "name": "color",
      "type": "ordinal",
      "domain": {"data": "table", "field": "text"},
      "range": ["#d5a928", "#652c90", "#939597"]
    }
  ],

  "marks": [
    {
      "type": "text",
      "from": {"data": "table"},
      "encode": {
        "enter": {
          "text": {"field": "text"},
          "align": {"value": "center"},
          "baseline": {"value": "alphabetic"},
          "fill": {"scale": "color", "field": "text"}
        },
        "update": {
          "fillOpacity": {"value": 1}
        },
        "hover": {
          "fillOpacity": {"value": 0.5}
        }
      },
      "transform": [
        {
          "type": "wordcloud",
          "size": [800, 400],
          "text": {"field": "text"},
          "rotate": {"field": "datum.angle"},
          "font": "Helvetica Neue, Arial",
          "fontSize": {"field": "datum.count"},
          "fontWeight": {"field": "datum.weight"},
          "fontSizeRange": [12, 56],
          "padding": 2
        }
      ]
    }
  ]
}
2

There are 2 answers

2
davidebacci On BEST ANSWER

Here's another solution which allows you to align the two values.

enter image description here

{
  "$schema": "https://vega.github.io/schema/vega/v5.json",
  "description": "A word cloud visualization depicting Vega research paper abstracts.",
  "width": 800,
  "height": 400,
  "padding": 0,
  "data": [
    {
      "name": "table",
      "values": [
        {"text": "apple", "weight": 15, "count": 1000},
        {"text": "banana", "weight": 20, "count": 1700},
        {"text": "orange", "weight": 20, "count": 1200}
      ],
      "transform": [
        {
          "type": "formula",
          "as": "angle",
          "expr": "[-45, 0, 45][~~(random() * 3)]"
        },
        {
          "type": "formula",
          "as": "text2",
          "expr": "[datum.text, datum.count]"
        },
        {
          "type": "formula",
          "as": "weight",
          "expr": "if(datum.text=='VEGA', 600, 300)"
        },
        {
          "type": "wordcloud",
          "size": [800, 400],
          "text": {"field": "text2"},
          "rotate": {"field": "angle"},
          "font": "Helvetica Neue, Arial",
          "fontSize": {"field": "count"},
          "fontWeight": {"field": "weight"},
          "fontSizeRange": [12, 56],
          "padding": 2
        }
      ]
    }
  ],
  "scales": [
    {
      "name": "color",
      "type": "ordinal",
      "domain": {"data": "table", "field": "text"},
      "range": ["#d5a928", "#652c90", "#939597"]
    }
  ],
  "marks": [
    {
      "type": "text",
      "from": {"data": "table"},
      "encode": {
        "enter": {
          "text": {"field": "text2"},
          "align": {"value": "center"},
          "baseline": {"value": "alphabetic"},
          "fill": {"scale": "color", "field": "text"}
        },
        "update": {
          "x": {"field": "x"},
          "y": {"field": "y"},
          "angle": {"field": "angle"},
          "fontSize": {"field": "fontSize"},
          "fillOpacity": {"value": 1}
        },
        "hover": {"fillOpacity": {"value": 0.5}}
      }
    },
 
  ]
}
2
davidebacci On

Here you go. This will look messy when you have lots of words though.

enter image description here

{
  "$schema": "https://vega.github.io/schema/vega/v5.json",
  "description": "A word cloud visualization depicting Vega research paper abstracts.",
  "width": 800,
  "height": 400,
  "padding": 0,
  "data": [
    {
      "name": "table",
      "values": [
        {"text": "apple", "weight": 15, "count": 1000},
        {"text": "banana", "weight": 20, "count": 1700},
        {"text": "orange", "weight": 20, "count": 1200}
      ],
      "transform": [
        {
          "type": "formula",
          "as": "angle",
          "expr": "[-45, 0, 45][~~(random() * 3)]"
        },
        {
          "type": "formula",
          "as": "weight",
          "expr": "if(datum.text=='VEGA', 600, 300)"
        },
        {
          "type": "wordcloud",
          "size": [800, 400],
          "text": {"field": "text"},
          "rotate": {"field": "angle"},
          "font": "Helvetica Neue, Arial",
          "fontSize": {"field": "count"},
          "fontWeight": {"field": "weight"},
          "fontSizeRange": [12, 56],
          "padding": 2
        }
      ]
    }
  ],
  "scales": [
    {
      "name": "color",
      "type": "ordinal",
      "domain": {"data": "table", "field": "text"},
      "range": ["#d5a928", "#652c90", "#939597"]
    }
  ],
  "marks": [
    {
      "type": "text",
      "from": {"data": "table"},
      "encode": {
        "enter": {
          "text": {"field": "text"},
          "align": {"value": "center"},
          "baseline": {"value": "alphabetic"},
          "fill": {"scale": "color", "field": "text"}
        },
        "update": {
          "x": {"field": "x"},
          "y": {"field": "y"},
          "angle": {"field": "angle"},
          "fontSize": {"field": "fontSize"},
          "fillOpacity": {"value": 1}
        },
        "hover": {"fillOpacity": {"value": 0.5}}
      }
    },
    {
      "type": "text",
      "from": {"data": "table"},
      "encode": {
        "enter": {
          "text": {"field": "count"},
          "align": {"value": "center"},
          "baseline": {"value": "alphabetic"},
          "fill": {"scale": "color", "field": "text"},
          "font": {"value": "Helvetica Neue, Arial"},
          "fontWeight": {"field": "weight"}
        },
        "update": {
          "x": {"field": "x"},
          "y": {"signal": "datum.y+15"},
          "angle": {"field": "angle"},
          "fontSize": {"signal": "10"},
          "fillOpacity": {"value": 1}
        },
        "hover": {"fillOpacity": {"value": 0.5}}
      }
    }
  ]
}