Skip to content

Instantly share code, notes, and snippets.

@jessvb
Last active September 19, 2023 16:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jessvb/3122b8ebb7564e8b35ee606399a12c29 to your computer and use it in GitHub Desktop.
Save jessvb/3122b8ebb7564e8b35ee606399a12c29 to your computer and use it in GitHub Desktop.
Normalized Stacked Bar Chart | Task Orientation | Vega-Lite

Notes

To create a JSON of your data that can be used in vega-lite, you can use python pandas to_json function with the 'records' orientation:

import pandas as pd

inputFile = "/path/to/csvs/inputfile.csv"
outputFile = "/path/to/output/ourputfile.json"

df = pd.DataFrame()
df = pd.read_csv(inputFile)
df.to_json(outputFile,orient="records")

Then, enter the data into vega-lite as in:

 {
  //...
  "data": {
    "values": // [enter json output from pandas here] e.g.,
      {
        "Group": "Overall",
        "Subset": "Overall",
        "Task-orientation": "Socially oriented",
        "Count": 38
      },
      {
        "Group": "Overall",
        "Subset": "Overall",
        "Task-orientation": "Task-oriented",
        "Count": 115
      },
      // ...
  }
}

Note that on the online vega-lite editor, you can directly get the SVG by copying the element in the inspector and pasting it into a text doc with the extension .svg.

image

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "data": {
    "values": [
    {
        "Theme": "Stressor: Physical",
        "Subtheme": "Navigating obstacles",
        "App Type": "Audio\/Haptic",
        "Value": 0,
        "Percent by App Type": 0.0
    },
    {
        "Theme": "Stressor: Physical",
        "Subtheme": "Gripping the phone",
        "App Type": "Audio\/Haptic",
        "Value": 2,
        "Percent by App Type": 3.278688525
    },
    {
        "Theme": "Stressor: Social-evaluative",
        "Subtheme": "Loud app sounds",
        "App Type": "Audio\/Haptic",
        "Value": 7,
        "Percent by App Type": 11.47540984
    },
    {
        "Theme": "Stressor: Social-evaluative",
        "Subtheme": "Social perception",
        "App Type": "Audio\/Haptic",
        "Value": 0,
        "Percent by App Type": 0.0
    },
    {
        "Theme": "Stressor: Cognitive",
        "Subtheme": "Bug/drift",
        "App Type": "Audio\/Haptic",
        "Value": 6,
        "Percent by App Type": 9.836065574
    },
    {
        "Theme": "Stressor: Cognitive",
        "Subtheme": "Problematic app visuals",
        "App Type": "Audio\/Haptic",
        "Value": 0,
        "Percent by App Type": 0.0
    },
    {
        "Theme": "Stressor: Cognitive",
        "Subtheme": "Distracting sounds",
        "App Type": "Audio\/Haptic",
        "Value": 1,
        "Percent by App Type": 1.639344262
    },
//...
]
},
  "repeat": {"column": ["App Type"]},
  "spec": {
    "mark": "bar",
    "encoding": {
      "y": {
        "field": "Subtheme",
        // "field": "Theme",
        "type": "nominal",
        // "sort": [
        //     "Stressor: Physical",
        //     "Stressor: Social-evaluative",
        //     "Stressor: Cognitive",
        //     "Stress Reducer: Social-evaluative",
        //     "Stress Reducer: Physical",
        //     "Stress Reducer: Cognitive",
        //     "Confident Scanning Correctly",
        //     "Not Confident Scanning Correctly",
        //     "Rewarding",
        //     "Stressor: Physical",
        //     "Stressor: Social-evaluative",
        //     "Stressor: Cognitive",
        //     "Stress Reducer: Social-evaluative",
        //     "Stress Reducer: Physical",
        //     "Stress Reducer: Cognitive",
        //     "Confident Scanning Correctly",
        //     "Not Confident Scanning Correctly",
        //     "Rewarding"
        // ]
        "sort": ["Navigating obstacles",
        "Gripping the phone",
        "Loud app sounds",
        "Social perception",
        "Bug/drift",
        "Problematic app visuals",
        "Distracting sounds",
        "Busyness of area",
        "Social acceptance of activity",
        "People automatically avoid you",
        "Aware of surroundings",
        "Prior experience",
        "Voiced encouragement",
        "Visualisation of mesh",
        "Learning a new skill"
        ]
      },
      "x": {
        // "aggregate": "sum",
        "field": "Value",
        // "field": "Percent by App Type",
        "type": "quantitative",
        "title": "Number of times mentioned"
        // "title": "Percent tags by app type"
      },
      "color": {"field": "App Type", "title": "Pilot App Version"},
      "yOffset": {"field": "App Type"},
    }
  },
  "config": {"mark": {"invalid": null}}
}

image

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "data": {
    "values": [
    {
        "codename": "RedAlpaca",
        "Valence (pre)": 4,
        "Valence (post)": 4,
        "Arousal (pre)": 2,
        "Arousal (post)": 3
    },
    {
        "codename": "YellowAlligator",
        "Valence (pre)": 4,
        "Valence (post)": 4,
        "Arousal (pre)": 2,
        "Arousal (post)": 3
    },
    {
        "codename": "OrangeAntelope",
        "Valence (pre)": 4,
        "Valence (post)": 3,
        "Arousal (pre)": 1,
        "Arousal (post)": 2
    },
// ...
  ]},
  "mark": "circle",
  "transform": [{"filter":{"field": "appType", "equal": "video"}}],
  "title": "Emotional affect for visual app users before scanning",
  "encoding": {
    "x": {
      "bin": {"maxbins": 6},
      "field": "Valence (pre)",
      "scale": {"domain": [1, 5]}
    },
    "y": {
      "bin": {"maxbins": 6},
      "field": "Arousal (pre)",
      "scale": {"domain": [1, 5]}
    },
    "size": {"aggregate": "count"}
  }
}

image

{
    "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
    "description": "A simple bar chart with embedded data.",
    "data": {
        "values": [
            {
                "codename": "bluealpaca",
                "measurementType": "Indoor Walk",
                "appType": "audio",
                "incremental-hr": 0.20652174,
                "scanning-level": "advanced",
            },
            {
                "codename": "bluealpaca",
                "measurementType": "Outdoor Walk",
                "appType": "audio",
                "incremental-hr": 4.33152174,
                "scanning-level": "advanced",
            },
            {
                "codename": "bluealpaca",
                "measurementType": "Indoor Scan",
                "appType": "audio",
                "incremental-hr": -0.16847826,
                "scanning-level": "advanced",
            },
            {
                "codename": "greenwalrus",
                "measurementType": "Indoor Walk",
                "appType": "video",
                "incremental-hr": 7.9,
                "scanning-level": "novice",
            },
//...
]},
    "mark": "boxplot",
    "width": 75,
    "title": {
        "text": "Incremental Heart Rate (ΔHR)",
        "frame": "bounds",
        "anchor": "middle",
        "offset": 20,
        "fontSize": 20
    },
    "encoding": {
        "x": {
            "field": "appType",
            "type": "nominal",
            "title": "App Version"
        },
        "color": {
            "field": "appType",
            "type": "nominal",
            "legend": null
        },
        "y": {
            "field": "incremental-hr",
            "type": "quantitative",
            "scale": {
                "zero": false
            },
            "title": "ΔHR (bpm)"
        },
        "column": {
            "field": "measurementType",
            "type": "nominal",
            "title": "Avg. HR Baseline Used to Obtain ΔHR:"
          }
    }
}
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"description": "A vertical box plot showing median and lower and upper quartiles of the distribution of heart rates.",
"data": {"values": [
{
"timestamp": "2023-03-29 16:02:05",
"heart_rate": 91,
"position_lat": 614559208.0,
"position_long": -1519396.0,
"distance": 0.09,
"enhanced_altitude": -57.4,
"enhanced_speed": 0.0,
"cadence": 0,
"fractional_cadence": 0.0,
"unknown_134": null,
"unknown_135": 52,
"unknown_136": 91,
"unknown_87": 0.0,
"codename": "CODENAME1",
"testType": "audio",
"testedFirst": "audio"
},
{
"timestamp": "2023-03-29 16:02:06",
"heart_rate": 91,
"position_lat": 614559203.0,
"position_long": -1519351.0,
"distance": 0.28,
"enhanced_altitude": -57.4,
"enhanced_speed": 0.0,
"cadence": 0,
"fractional_cadence": 0.0,
"unknown_134": null,
"unknown_135": 52,
"unknown_136": 91,
"unknown_87": 0.0,
"codename": "CODENAME1",
"testType": "audio",
"testedFirst": "audio"
},
// ...
]},
"mark": "boxplot",
"title": "Heart Rate w.r.t. App Testing Order",
"encoding": {
"x": {
"field": "testType",
"type": "nominal",
"title": "App"
},
"color": {"field": "testType", "type": "nominal", "legend": null},
"y": {
"field": "heart_rate",
"type": "quantitative",
"scale": {"zero": false},
"title": "Heart Rate (bpm)"
},
"column": {
"field": "testedFirst",
"type": "nominal",
"title": "App Used First"
}
}
}
// Alternative chart encodingss:
"title": "Heart Rate Using Each App",
"encoding": {
"x": {
"field": "testType",
"type": "nominal",
"title": "App"
},
"color": {"field": "testType", "type": "nominal", "legend": null},
"y": {
"field": "heart_rate",
"type": "quantitative",
"scale": {"zero": false},
"title": "Heart Rate (bpm)"
},
}
"title": "Heart Rate Per User",
"encoding": {
"x": {
"field": "codename",
"type": "nominal",
"title": "Code Name"
},
"y": {
"field": "heart_rate",
"type": "quantitative",
"scale": {"zero": false},
"title": "Heart Rate (bpm)"
},
}
"title": "Heart Rate Per User Per App",
"encoding": {
"x": {
"field": "testType",
"type": "nominal",
"title": "App"
},
"color": {"field": "testType", "type": "nominal", "legend": null},
"y": {
"field": "heart_rate",
"type": "quantitative",
"scale": {"zero": false},
"title": "Heart Rate (bpm)"
},
"column": {
"field": "codename",
"type": "nominal",
"title": "Code Name"
}
}
}
{
"$schema": "https://vega.github.io/schema/vega-lite/v5.json",
"data": {
"values": [
{
"Group": "Overall",
"Subset": "Overall",
"Task-orientation": "Socially oriented",
"Count": 38
},
{
"Group": "Overall",
"Subset": "Overall",
"Task-orientation": "Task-oriented",
"Count": 115
},
{
"Group": "Non-WEIRD/WEIRD",
"Subset": "Non-WEIRD",
"Task-orientation": "Socially oriented",
"Count": 22
},
{
"Group": "Non-WEIRD/WEIRD",
"Subset": "Non-WEIRD",
"Task-orientation": "Task-oriented",
"Count": 52
},
{
"Group": "Non-WEIRD/WEIRD",
"Subset": "WEIRD",
"Task-orientation": "Socially oriented",
"Count": 16
},
{
"Group": "Non-WEIRD/WEIRD",
"Subset": "WEIRD",
"Task-orientation": "Task-oriented",
"Count": 63
},
{
"Group": "Child/Parent",
"Subset": "Child",
"Task-orientation": "Socially oriented",
"Count": 27
},
{
"Group": "Child/Parent",
"Subset": "Child",
"Task-orientation": "Task-oriented",
"Count": 66
},
{
"Group": "Child/Parent",
"Subset": "Parent",
"Task-orientation": "Socially oriented",
"Count": 11
},
{
"Group": "Child/Parent",
"Subset": "Parent",
"Task-orientation": "Task-oriented",
"Count": 49
},
{
"Group": "Child/Parent Non-WEIRD",
"Subset": "Child, Non-WEIRD",
"Task-orientation": "Socially oriented",
"Count": 16
},
{
"Group": "Child/Parent Non-WEIRD",
"Subset": "Child, Non-WEIRD",
"Task-orientation": "Task-oriented",
"Count": 30
},
{
"Group": "Child/Parent Non-WEIRD",
"Subset": "Parent, Non-WEIRD",
"Task-orientation": "Socially oriented",
"Count": 6
},
{
"Group": "Child/Parent Non-WEIRD",
"Subset": "Parent, Non-WEIRD",
"Task-orientation": "Task-oriented",
"Count": 22
},
{
"Group": "Child/Parent WEIRD",
"Subset": "Child, WEIRD",
"Task-orientation": "Socially oriented",
"Count": 11
},
{
"Group": "Child/Parent WEIRD",
"Subset": "Child, WEIRD",
"Task-orientation": "Task-oriented",
"Count": 36
},
{
"Group": "Child/Parent WEIRD",
"Subset": "Parent, WEIRD",
"Task-orientation": "Socially oriented",
"Count": 5
},
{
"Group": "Child/Parent WEIRD",
"Subset": "Parent, WEIRD",
"Task-orientation": "Task-oriented",
"Count": 27
}
]
},
"mark": "bar",
"width": {"step": 17},
"encoding": {
"y": {
"aggregate": "sum",
"field": "Count",
"title": "Fraction Task-Oriented",
"stack": "normalize"
},
"x": {"field": "Subset", "axis": {"title": ""}},
"color": {
"field": "Task-orientation",
"scale": {"range": ["#FFB000", "#648FFF"]}
},
"column": {
"field": "Group",
"type": "ordinal",
"title": "Preferences for Task-Orientation of Agents",
"header": {"titleFontSize": 15, "labelFontSize": 0},
"sort": {"op": "min", "field": "Count"}
}
},
"resolve": {"scale": {"x": "independent"}}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment