From ff86499235d47a307bfe80f473113035c94213af Mon Sep 17 00:00:00 2001 From: Danai Kafetzaki Date: Mon, 23 Mar 2020 22:17:14 +0100 Subject: [PATCH 01/17] Add files via upload --- pages/vega-in-r/1_setting-things-up.md | 13 + pages/vega-in-r/2_simple-barchart.md | 175 ++++ pages/vega-in-r/3_changing-data.md | 257 +++++ pages/vega-in-r/4_simple-interaction.md | 192 ++++ pages/vega-in-r/5_field-transform.md | 1080 +++++++++++++++++++++ pages/vega-in-r/6_data-transformations.md | 194 ++++ 6 files changed, 1911 insertions(+) create mode 100644 pages/vega-in-r/1_setting-things-up.md create mode 100644 pages/vega-in-r/2_simple-barchart.md create mode 100644 pages/vega-in-r/3_changing-data.md create mode 100644 pages/vega-in-r/4_simple-interaction.md create mode 100644 pages/vega-in-r/5_field-transform.md create mode 100644 pages/vega-in-r/6_data-transformations.md diff --git a/pages/vega-in-r/1_setting-things-up.md b/pages/vega-in-r/1_setting-things-up.md new file mode 100644 index 0000000..86ecad2 --- /dev/null +++ b/pages/vega-in-r/1_setting-things-up.md @@ -0,0 +1,13 @@ +--- +title: Setting things up +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-a-simple-barchart.html +folder: vega-in-r +series: vega-in-r-series +weight: 1 +--- + +Setting things up - to be updated... + +{% include custom/series_vega-in-r_next.html %} diff --git a/pages/vega-in-r/2_simple-barchart.md b/pages/vega-in-r/2_simple-barchart.md new file mode 100644 index 0000000..82787e0 --- /dev/null +++ b/pages/vega-in-r/2_simple-barchart.md @@ -0,0 +1,175 @@ +--- +title: A simple barchart +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-a-simple-barchart.html +folder: vega-in-r +series: vega-in-r-series +weight: 2 +--- +Here is a very simple barchart defined in altair in R. + +
+ + +The dataset of the chart is: + +```R +Var1 = c("a","b","c","d","e") +Var2 = c(11, 19, 22, 8, 14) +Var3 = c("type1","type1","type2","type1","type2") +dataset = data.frame(Var1, Var2, Var3) +``` + +and below is the code used to generate it: + + +```R +chart_1 = + alt$Chart(dataset)$ + mark_bar()$ + encode( + x = "Var1:O", + y = "Var2:Q" + # color = "Var3:N" + )$properties( + height=200, + width=400 + ) +``` + +What is the syntax in the altair R? It is similar to the Python altair and the major difference is the usage of the operator `$` to access attributes, instead of `.`. +We use the object `alt` to access the Altair API and the first basic argument is the `alt$Chart`. +- The `data` to be visualised is called inside the `alt$Chart`. +- The `mark` is specifed after `mark_`. +- The `encoding` determines the mapping between the channels and the data. Here, `x` and `y` are the position channels. The field type is specified after the field name. `O` stands for ordinal and `Q` for quantitative. +- The height and width of the plot is specified inside `properties`. + + +{:.exercise} +**Exercise** - Make yourself comfortable with the syntax of this basic altair chart. Use the color channel for `Var3` to make the chart below. Then, change the mark and add a variable for size. + +
+ + +{:.exercise} +**Exercise** - Change the height and width of the panel and remake the plot above. + + +{% include custom/series_vega-in-r_next.html %} diff --git a/pages/vega-in-r/3_changing-data.md b/pages/vega-in-r/3_changing-data.md new file mode 100644 index 0000000..63e04bc --- /dev/null +++ b/pages/vega-in-r/3_changing-data.md @@ -0,0 +1,257 @@ +--- +title: A case study +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-a-case-study.html +folder: vega-in-r +series: vega-in-r-series +weight: 3 +--- +Let's now use a more realistic example and visualize the natural diasters dataset [https://ourworldindata.org/natural-disasters.html](https://ourworldindata.org/natural-disasters.html). +This dataset is included in the vega_datasets package [https://github.com/vega/vega-datasets.html] (https://github.com/vega/vega-datasets.html). + +You can import the datasets using the altair library. +vega_data = altair::import_vega_data() + +See the list of the available datasets +```R +vega_data$list_datasets() +``` + +and select the one you want to visualise. +```R +data_source = vega_data$disasters() +``` + +Alternatively, you may read the data from a url using: +```R +data_source = read.csv(url("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")) +``` + +or load the data from a local file using standard R code. + +After importing the data, we can take a first look using standard R code: + +```R +str(data_source) +summary(data_source) +head(data_source); tail(data_source) +``` + +We can now make a plot similar to the one at [https://altair-viz.github.io/gallery/natural_disasters.html](https://altair-viz.github.io/gallery/natural_disasters.html) +For now, we may filter tha data in R and use the subset of the data to make the plot in altair R. On the data transformations section we will see how to do the filtering inside the altair specification. + +
+ + + +Below is the code to make this plot. + +```R +data_source_subset = subset(data_source, data_source$Entity != "All natural disasters") + +chart_disasters = + alt$Chart(data_source_subset)$ + mark_circle( + opacity=0.8, + stroke='black', + strokeWidth=1 + )$ + encode( + x = "Year:O", + y = "Entity:N", + color = "Entity:N", + size = "Deaths:Q" + )$properties( + height=200, + width=400 + ) +``` +The global properties of the circles are specified inside the mark attribute and the properties that depend on the data inside the encoding. +Using the mark type `rect` with `color` and `opacity` channels we can make a heatmap plot. + + +```R +chart_disasters = + alt$Chart(data_source_subset)$ + mark_circle( + opacity=0.8, + stroke='black', + strokeWidth=1 + )$ + encode( + x = "Year:O", + y = "Entity:N", + color = "Entity:N", + size = "Deaths:Q" + )$properties( + height=200, + width=400 + ) +``` + + +
+ + +Next, using the code below, we can make a time series plot of deaths from all natural disasters from 1900 until 2017. + +```R +data_source_subset = subset(data_source, data_source$Entity == "All natural disasters") + +chart_disasters = alt$Chart(data_source_subset)$ + mark_line()$ + encode( + x='Year:Q', + y='Deaths:Q', + tooltip = c("Year", "Deaths") + )$properties( + height=300, + width=600 +) +``` + +
+ + + +{:.exercise} +**Exercise** - Use the `color` channel to make a time series plot per Entity. + +{:.exercise} +**Exercise** - Change the field types. What is the result? + +{:.exercise} +**Exercise** - Make a barchart for total deaths per Entity. Hint: You may do the calculation in R or try a calculation inside encoding. + + +{% include custom/series_vega-in-r_next.html %} diff --git a/pages/vega-in-r/4_simple-interaction.md b/pages/vega-in-r/4_simple-interaction.md new file mode 100644 index 0000000..21935a5 --- /dev/null +++ b/pages/vega-in-r/4_simple-interaction.md @@ -0,0 +1,192 @@ +--- +title: Simple Interaction +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-simple-interaction.html +folder: vega-in-r +series: vega-in-r-series +weight: 4 +--- + +One of the main advantages to use the altair package is the fact that supports the generation of interactive graphics. The code required for adding a simple interaction is relatively short. + +# Tooltip + +A tooltip can be added to the plot using `tooltip()` inside encode. For one variable displayed in the tooltip we can use: + +```R +... +tooltip = "Variable_1" +... +``` + +and for more than one variable, we can use the R function c() as illustrated below: + +```R +... +tooltip = c("Variable_1", "Variable_2") +... +``` + +Mind that if you are importing the data from a url directly in the plot specification, you may need to specify the field type. + + +
+ + +{:.exercise} +**Exercise** - Add a tooltip in the heatmap we created in the previous section, to get the graph illustrated above. + + +# Zooming and Panning + +We illustrate two ways of making a graph zoomable and pannable. The first one is by adding the `intreactive()` attribute, as illustrated below: + +```R +$interactive() +``` + +A second option is to specify the selection outside the plot code and then use it inside the `add_selection` attribute in the chart code. +The second option is an interval selection using a scale binding. + +```R +selection = alt$selection_interval(bind='scales') + +chart = alt$Chart(data_source_subset)$ +..... +$add_selection( + selection + ) +``` + +
+ + + +{:.exercise} +**Exercise** - Make the time series plot of all natural distasters interactive, to get the graph illustrated above. Use both ways of making it zoomable and pannable. + +{:.exercise} +**Exercise** - Go through the other selection types supported in altair. [https://altair-viz.github.io/user_guide/generated/api/altair.selection_interval.html#altair.selection_interval.html](https://altair-viz.github.io/user_guide/generated/api/altair.selection_interval.html#altair.selection_interval) + + +{% include custom/series_vega-in-r_next.html %} diff --git a/pages/vega-in-r/5_field-transform.md b/pages/vega-in-r/5_field-transform.md new file mode 100644 index 0000000..a8332ad --- /dev/null +++ b/pages/vega-in-r/5_field-transform.md @@ -0,0 +1,1080 @@ +--- +title: Field Transform +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-field-transform.html +folder: vega-in-r +series: vega-in-r-series +weight: 5 +--- + +Since we are wokring in R, we can modify the data outside the plot specification and then use the modified dataset inside the plot encoding. +However, using the altair package, calculations inside the plot specification can be sometimes easier. In this section, we are discussing field trasforms that can be done inside encoding. +As we have seen from the beginning of this tutorial, the `encoding` determines the mapping between the channels and the data. We have already used encoding channels such as position channels `x` and `y` and mark property channels, for instance, `color` and `opacity`. +We only need to add `bin = TRUE` in the `x` position channel of a quantitative field to use the binned version of the field in the plot. +Below, there is the code to produce a barchart of the sum of deaths versus the binned years. + +```R +data_source_subset = subset(data_source, data_source$Entity == "All natural disasters") + +chart_disasters = alt$Chart(data_source_subset)$ + mark_bar()$ + encode( + alt$X("Year:Q", bin = TRUE), + y='sum(Deaths):Q', + tooltip = 'sum(Deaths):Q' +) +``` + +
+ + +{:.exercise} +**Exercise** - Check the documentation of the binning parameters [https://altair-viz.github.io/user_guide/generated/core/altair.BinParams.html](https://altair-viz.github.io/user_guide/generated/core/altair.BinParams.html) and increase the value of the maximum number of bins. + +
+ + + +{:.exercise} +**Exercise** - Using `data_source_subset = subset(data_source, data_source$Entity != "All natural disasters")` make a line plot that shows the deaths from all natural disasters versus time. + +{:.exercise} +**Exercise** - Using `data_source_subset = subset(data_source, data_source$Entity != "All natural disasters")` make a heatmap that shows the count of disasters per year, like the one below. + + +
+ + + +Another filed transformation is the one that scales the original field domain to the range we specify. +For instance, we can transform a quantitative field using the log scale. + + +```R +chart_disasters = alt$Chart("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")$ + mark_bar()$encode( + x = 'Entity:N', + alt$Y('sum(Deaths):Q', scale=alt$Scale(type='log')) + )$properties( + height=300, + width=600 +) + +``` + +
+ + + +Fortunately, not in all years from 1900 to 2017 all types of registered disasters occured. Did you notice that in 1904 there is no natural disaster registered? +Let's enrich the dataset in R with a variable for missing values based on the year. + +```R +data_source = read.csv(url("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")) # original data +Year = seq(1900, 2017, 1) # create year vector +Entity = sort(rep(unique(data_source$Entity), 118)) # create entity vector +data_mod = cbind.data.frame(Year, Entity) # create dataframe with complete set of year and entity +data_source_modified = merge(data_source, data_mod, by = c("Year", "Entity"), all = T) # merge df with original data +data_source_modified[is.na(data_source_modified$Deaths),"Deaths"] = 0 # replace NA with zero +data_source_modified$Missing = NULL # create new variable +data_source_modified[data_source_modified$Deaths == 0,"Missing"] = "1" # the value for missing +data_source_modified[data_source_modified$Deaths != 0,"Missing"] = "0" # the value for non-missing +str(data_source_modified) # look at the new data structure +rm(Year, Entity, data_mod) # remove objects that are not needed +``` + +Now we can plot the full time series, and specify a custom color scale for the presence of absence of the year in the data. +So, the domain of the data is `0` and `1` and the custom range is the two colors of our preference. + +```R +domain_color = c("0", "1") +range_color = c('black', 'red') + +data_source_subset = subset(data_source_modified, data_source_modified$Entity == "All natural disasters") + +chart_disasters = alt$Chart(data_source_subset)$ + mark_circle( + opacity=0.8, + size = 50 + )$ + encode( + x='Year:O', + y='Deaths:Q', + color=alt$Color('Missing', scale=alt$Scale(domain=domain_color, range=range_color)), + tooltip = c("Year", "Deaths") + )$properties( + height=300, + width=600 + )$ + interactive() +``` + + +
+ + + + +{% include custom/series_vega-in-r_next.html %} diff --git a/pages/vega-in-r/6_data-transformations.md b/pages/vega-in-r/6_data-transformations.md new file mode 100644 index 0000000..e775d46 --- /dev/null +++ b/pages/vega-in-r/6_data-transformations.md @@ -0,0 +1,194 @@ +--- +title: Data Transformations +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-data-transformations.html +folder: vega-in-r +series: vega-in-r-series +weight: 6 +--- + +As mentioned in the documentation of altair, [https://altair-viz.github.io/user_guide/transform/index.html](https://altair-viz.github.io/user_guide/transform/index.html) in most cases, it is suggested to perform transformations outside the chart definition, so in our case using R. Of course, data transforms inside the chart can also be useful in some cases. +So far, we have been filtering the data in R and then using the modified data in the chart specification. Now, we use the `transform_filter()` to subset the data inside the chart. We make the linechart we have seen in a previous section using the code below: + +```R +chart_disasters = alt$Chart("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")$ + mark_line()$ + encode( + x='Year:Q', + y='Deaths:Q', + tooltip = c("Year", "Deaths") + )$properties( + height=300, + width=600 + )$transform_filter( + alt$FieldEqualPredicate(field = "Entity", equal = "All natural disasters") +) +``` + +
+ + + +{:.exercise} +**Exercise** - Use the filter transform to obtain the data related to volcanic activity and earthquake and make an area chart like the one below. Hint: Go through the documentation for Field Predicates at [https://altair-viz.github.io/user_guide/transform/filter.html#user-guide-filter-transform](https://altair-viz.github.io/user_guide/transform/filter.html#user-guide-filter-transform). + +
+ + +We now also use the `transform_window()` to compute and plot a windowed aggregation of the deaths over all available years. + + +```R +chart_disasters = alt$Chart("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")$ + transform_window( + cumulative_count='sum(Deaths)' +)$mark_area()$encode( + x='Year:O', + y='cumulative_count:Q', + tooltip = c("Year:Q", 'cumulative_count:Q') +)$transform_filter( + alt$FieldEqualPredicate(field = "Entity", equal = "All natural disasters") +)$properties( + height=300, + width=600 +) +``` + +
+ + + + +{% include custom/series_vega-in-r_next.html %} From af0b92bb5cae7026bd02f74105574073be5e6692 Mon Sep 17 00:00:00 2001 From: Danai Kafetzaki Date: Tue, 31 Mar 2020 21:02:06 +0200 Subject: [PATCH 02/17] Add files via upload --- pages/vega-in-r/brush-and-link.md | 21526 ++++++++++++++++++++ pages/vega-in-r/changing-data.md | 289 + pages/vega-in-r/concatenated-chart.md | 278 + pages/vega-in-r/data-transformations.md | 205 + pages/vega-in-r/faceted-chart.md | 7894 +++++++ pages/vega-in-r/field-transform.md | 1088 + pages/vega-in-r/layered-chart.md | 8000 ++++++++ pages/vega-in-r/setting-things-up.md | 57 + pages/vega-in-r/simple-barchart.md | 244 + pages/vega-in-r/simple-interaction.md | 191 + pages/vega-in-r/vega-in-r_landing_page.md | 25 + pages/vega-in-r/widgets.md | 7343 +++++++ 12 files changed, 47140 insertions(+) create mode 100644 pages/vega-in-r/brush-and-link.md create mode 100644 pages/vega-in-r/changing-data.md create mode 100644 pages/vega-in-r/concatenated-chart.md create mode 100644 pages/vega-in-r/data-transformations.md create mode 100644 pages/vega-in-r/faceted-chart.md create mode 100644 pages/vega-in-r/field-transform.md create mode 100644 pages/vega-in-r/layered-chart.md create mode 100644 pages/vega-in-r/setting-things-up.md create mode 100644 pages/vega-in-r/simple-barchart.md create mode 100644 pages/vega-in-r/simple-interaction.md create mode 100644 pages/vega-in-r/vega-in-r_landing_page.md create mode 100644 pages/vega-in-r/widgets.md diff --git a/pages/vega-in-r/brush-and-link.md b/pages/vega-in-r/brush-and-link.md new file mode 100644 index 0000000..a028b84 --- /dev/null +++ b/pages/vega-in-r/brush-and-link.md @@ -0,0 +1,21526 @@ +--- +title: Brush and link +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-brush-and-link.html +folder: vega-in-r +series: vega-in-r-series +weight: 10 +--- + +We have seen how to concatenate charts, we may now see how to connect them interactively. +- To do so, we first create a static chart using the step 1 of the code below. +- The second step is to add a selection. Here we add a selection of type `interval` but a selection can also be `single` or `multi` [altair.selection reference](https://altair-viz.github.io/user_guide/generated/api/altair.selection.html?highlight=selection#altair.selection). In step 2, we also name the selection 'brush' and we update the static chart by including the selection function. +- Finally, in step 3, we update the color encoding of the data, so that every time the chart is brused the data inside the selection are colored, based on the nominal variable `Missing`, and the rest are colored lightgray. + +```R +data_source_modified_subset = subset(data_source_modified, data_source_modified$Entity != "All natural disasters") + +# step1 +domain_color = c("0", "1") +range_color = c('black', 'red') + +chart_static = alt$Chart(data_source_modified_subset)$ + mark_circle( + opacity = 0.8, + size = 50 + )$ + encode( + x = 'Year:O', + y = 'Deaths:Q', + color = alt$Color('Missing', scale=alt$Scale(domain = domain_color, range = range_color)) + )$ + properties( + height = 300, + width = 600 + ) + +# step2 +brush = alt$selection_interval() +chart_brush = chart_static$add_selection(brush) + +# step3 +chart_1 = chart_brush$encode( + color = alt$condition(brush, "Missing:N", alt$value("lightgray")) + ) +``` + +
+ + +
+ +Now that we have created our brushable chart, we may decrease the size of the first chart, so that we can easily display two charts in the screen. +If we now make a second chart that inherits all the properties of the first chart but we only change the x position encoding to `Entity`, we get the two-way brushable and linkable visalisation below. + +```R +chart_2a = chart_1$properties(width = 300, height = 300) +chart_2b = chart_2a$encode(x = "Entity:N") + +chart_distasters = (chart_2a | chart_2b) +``` + +
+ + +
+ +{:.exercise} +**Exercise** - Make a one-way brushable and linkable chart of the deaths versus time per entity. The interval selection appears in a barchart below. + + +
+ + + + +{% include custom/series_vega-in-r_next.html %} diff --git a/pages/vega-in-r/changing-data.md b/pages/vega-in-r/changing-data.md new file mode 100644 index 0000000..aefa001 --- /dev/null +++ b/pages/vega-in-r/changing-data.md @@ -0,0 +1,289 @@ +--- +title: Changing data +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-changing-data.html +folder: vega-in-r +series: vega-in-r-series +weight: 3 +--- +Let's now use a more realistic example and visualize a dataset included in the `vega_datasets` package [https://github.com/vega/vega-datasets.html](https://github.com/vega/vega-datasets.html). + +You can import the vega datasets using the altair library. +```R +vega_data = altair::import_vega_data() +``` + +See the list of the available datasets +```R +vega_data$list_datasets() +``` + +and select the one you want to work with. Here, we are using the dataset for [Natural Disasters from Our World in Data](https://ourworldindata.org/natural-disasters.html). +```R +data_source = vega_data$disasters() +``` + +Alternatively, you may load data from a local file using standard R code, or read the data from a url using: +```R +data_source = read.csv(url("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")) +``` + +After importing the data, we can take a first look using standard R code: + +```R +str(data_source) +summary(data_source) +head(data_source); tail(data_source) +``` + +```R +> str(data_source) +'data.frame': 803 obs. of 3 variables: + $ Entity: Factor w/ 11 levels "All natural disasters",..: 1 1 1 1 1 1 1 1 1 1 ... + $ Year : int 1900 1901 1902 1903 1905 1906 1907 1908 1909 1910 ... + $ Deaths: int 1267360 200018 46037 6506 22758 42970 1325641 75033 1511524 148233 ... +> summary(data_source) + Entity Year Deaths + All natural disasters:117 Min. :1900 Min. : 1 + Earthquake :111 1st Qu.:1946 1st Qu.: 270 + Extreme weather :111 Median :1975 Median : 1893 + Flood : 89 Mean :1969 Mean : 81213 + Landslide : 79 3rd Qu.:1996 3rd Qu.: 10362 + Epidemic : 69 Max. :2017 Max. :3706227 + (Other) :227 +> head(data_source) + Entity Year Deaths +1 All natural disasters 1900 1267360 +2 All natural disasters 1901 200018 +3 All natural disasters 1902 46037 +4 All natural disasters 1903 6506 +5 All natural disasters 1905 22758 +6 All natural disasters 1906 42970 +> tail(data_source) + Entity Year Deaths +798 Wildfire 2012 21 +799 Wildfire 2013 35 +800 Wildfire 2014 16 +801 Wildfire 2015 67 +802 Wildfire 2016 39 +803 Wildfire 2017 75 +``` + +We can now make an altair R plot similar to the one at altair Python [https://altair-viz.github.io/gallery/natural_disasters.html](https://altair-viz.github.io/gallery/natural_disasters.html) +For now, we may filter the data in R and use the subset of the data to make the chart. On the data transform section we will see how to do the filtering inside the altair chart specification. + +
+ +
+ + + +Below is the code to make this plot. +```R +data_source_subset = subset(data_source, data_source$Entity != "All natural disasters") + +chart_disasters = + alt$Chart(data_source_subset)$ + mark_circle( + opacity=0.8, + stroke='black', + strokeWidth=1)$ + encode( + x = "Year:O", + y = "Entity:N", + color = "Entity:N", + size = "Deaths:Q" + )$ + properties( + height=200, + width=500 + ) +``` +The global properties of the circles are specified inside the mark attribute and the properties that depend on the data inside the encoding. +Using the mark type `rect` with `color` and `opacity` channels we can make a heatmap plot. + + +```R +chart_disasters_2 = + alt$Chart(data_source_subset)$ + mark_rect()$ + encode( + x = "Entity:O", + y = "Year:O", + color = "Entity:N", + opacity = 'Deaths:Q', + tooltip = c("Year:O", "Deaths:Q") + )$ + properties( + height=600, + width=200 + ) +``` + + +
+ + +Next, using the code below, we can make a time series plot of deaths from all natural disasters from 1900 until 2017. + +```R +data_source_subset = subset(data_source, data_source$Entity == "All natural disasters") + +chart_disasters = alt$Chart(data_source_subset)$ + mark_line()$ + encode( + x='Year:Q', + y='Deaths:Q', + tooltip = c("Year", "Deaths") + )$ + properties( + height=300, + width=600 + ) +``` + +
+ + + +{:.exercise} +**Exercise** - Use the `color` channel to make a time series plot per Entity. + +{:.exercise} +**Exercise** - Change the field types. What is the result? + +{:.exercise} +**Exercise** - Make a barchart for total Deaths per Entity. Hint: You may do the calculation in R or try a calculation inside encoding. + + +{% include custom/series_vega-in-r_next.html %} diff --git a/pages/vega-in-r/concatenated-chart.md b/pages/vega-in-r/concatenated-chart.md new file mode 100644 index 0000000..8eb5148 --- /dev/null +++ b/pages/vega-in-r/concatenated-chart.md @@ -0,0 +1,278 @@ +--- +title: Concatenated chart +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-concatenated-chart.html +folder: vega-in-r +series: vega-in-r-series +weight: 8 +--- + +To concatenate charts horizontally we can use the `|` operator: `chart_1 | chart_2`. +For vertical concatenation the operator `&` can be used: `chart_1 & chart_2`. +Below, we are combining four charts to create a 2x2 visualisation using `(chart_1 | chart_2) & (chart_3 | chart_4)`. +To specify a title in each plot, we use `title = 'The Title'` inside `$properties()`. + +```R +chart_disasters_1 = alt$Chart("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")$ + mark_line()$ + encode( + x = 'Year:O', + y = 'Deaths:Q', + tooltip = 'Deaths:Q' + )$ + transform_filter( + alt$FieldEqualPredicate(field = "Entity", equal = "Landslide") + )$ + properties( + width = 400, + height = 200, + title = 'Landslide' + )$ + interactive() + +chart_disasters_2 = alt$Chart("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")$ + mark_line()$ + encode( + x = 'Year:O', + y = 'Deaths:Q', + tooltip = 'Deaths:Q' + )$ + transform_filter( + alt$FieldEqualPredicate(field = "Entity", equal = "Volcanic activity") + )$ + properties( + width = 400, + height = 200, + title = 'Volcanic activity' + )$ + interactive() + +chart_disasters_3 = alt$Chart("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")$ + mark_line()$ + encode( + x = 'Year:O', + y = 'Deaths:Q', + tooltip = 'Deaths:Q' + )$ + transform_filter( + alt$FieldEqualPredicate(field = "Entity", equal = "Wildfire") + )$ + properties( + width = 400, + height = 200, + title = 'Wildfire' + )$ + interactive() + +chart_disasters_4 = alt$Chart("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")$ + mark_line()$ + encode( + x = 'Year:O', + y = 'Deaths:Q', + tooltip = 'Deaths:Q' + )$ + transform_filter( + alt$FieldEqualPredicate(field = "Entity", equal = "Mass movement (dry)") + )$ + properties( + width = 400, + height = 200, + title = 'Mass movement (dry)' + )$ + interactive() + +chart_combined = (chart_disasters_1 | chart_disasters_2) & (chart_disasters_3 | chart_disasters_4) +``` + + +
+ + + +{% include custom/series_vega-in-r_next.html %} diff --git a/pages/vega-in-r/data-transformations.md b/pages/vega-in-r/data-transformations.md new file mode 100644 index 0000000..b9adae4 --- /dev/null +++ b/pages/vega-in-r/data-transformations.md @@ -0,0 +1,205 @@ +--- +title: Data Transform +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-data-transformations.html +folder: vega-in-r +series: vega-in-r-series +weight: 6 +--- + +As mentioned in the documentation of altair, [https://altair-viz.github.io/user_guide/transform/index.html](https://altair-viz.github.io/user_guide/transform/index.html) in most cases, it is suggested to perform transformations outside the chart definition, so in our case using R. Of course, data transforms inside the chart can also be useful in some cases. +So far, we have been filtering the data in R and then using the modified data in the chart specification. Now, we use the `transform_filter()` to subset the data inside the chart. We make the linechart we have seen in a previous section using the code below: + +```R +chart_disasters = alt$Chart("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")$ + mark_line()$ + encode( + x = 'Year:Q', + y = 'Deaths:Q', + tooltip = c("Year", "Deaths") + )$ + properties( + height = 300, + width = 600 + )$ + transform_filter( + alt$FieldEqualPredicate(field = "Entity", equal = "All natural disasters") + ) +``` + +
+ + +
+ +We use the field predicates to assess whether a data point satisfied certain conditions. As mentioned in the [field predicates reference](https://altair-viz.github.io/user_guide/transform/filter.html#field-predicates) the `FieldEqualPredicate` evaluates whether a field is equal to a particular value. The variable is the first argument and the condition is the second argument. Go through the field predicates altair documentation and [vega-lite documentation](https://vega.github.io/vega-lite/docs/predicate.html#field-predicate) and use the `FieldOneOfPredicate` for the exercise below. + + +{:.exercise} +**Exercise** - Use the filter transform to obtain the data related to volcanic activity and earthquake and make an area chart like the one below. + +
+ + +
+ +We now also use the `transform_window()` for data transformation to compute and plot a windowed aggregation of the deaths over all available years. + + +```R +chart_disasters = alt$Chart("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")$ + transform_window( + cumulative_count='sum(Deaths)' + )$ + mark_area()$ + encode( + x = 'Year:O', + y = 'cumulative_count:Q', + tooltip = c("Year:Q", 'cumulative_count:Q') + )$transform_filter( + alt$FieldEqualPredicate(field = "Entity", equal = "All natural disasters") + )$ + properties( + height = 300, + width = 600 + ) +``` + +
+ + + + +{% include custom/series_vega-in-r_next.html %} diff --git a/pages/vega-in-r/faceted-chart.md b/pages/vega-in-r/faceted-chart.md new file mode 100644 index 0000000..0c4b902 --- /dev/null +++ b/pages/vega-in-r/faceted-chart.md @@ -0,0 +1,7894 @@ +--- +title: Faceted chart +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-faceted-chart.html +folder: vega-in-r +series: vega-in-r-series +weight: 9 +--- + +For faceting, we can use `facet` inside `$encode()`. The height and width we specify, refer to each individual plot. +If we do not specify the number of columns `columns = 3` all individual charts are concatenated horizontally. +We also see that with the `facet` function, a title of each chart is automatically displayed for each level of the variable we are faceting. + +```R +chart_disasters = alt$Chart(data_source_modified)$ + mark_circle( + opacity = 0.8, + size = 20 + )$ + encode( + x = 'Year:O', + y = 'Missing:N', + color = 'Missing:N', + facet = alt$Facet('Entity:N', columns = 3), + tooltip = "Year:Q" + )$ + properties( + width = 180, + height = 90 + )$ + interactive() +``` + + +
+ + +
+ +{:.exercise} +**Exercise** - Make a faceted chart for the time series per natural disaster. + +{:.exercise} +**Exercise** - What is the problem with the chart made above and how could you remake it without using `facet`? + + +{% include custom/series_vega-in-r_next.html %} diff --git a/pages/vega-in-r/field-transform.md b/pages/vega-in-r/field-transform.md new file mode 100644 index 0000000..e9a1f85 --- /dev/null +++ b/pages/vega-in-r/field-transform.md @@ -0,0 +1,1088 @@ +--- +title: Field Transform +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-field-transform.html +folder: vega-in-r +series: vega-in-r-series +weight: 5 +--- + +Since we are wokring in R, we can modify the data outside the plot specification and then use the modified dataset inside the plot encoding. +However, using the altair package, calculations inside the plot specification can be sometimes easier. In this section, we are discussing field trasforms that can be done inside encoding. +As we have seen from the beginning of this tutorial, the `encoding` determines the mapping between the channels and the data. We have already used encoding channels such as position channels `x` and `y` and mark property channels, for instance, `color` and `opacity`. +We only need to add `bin = TRUE` in the `x` position channel of a quantitative field to use the binned version of the field in the plot. +Below, there is the code to produce a barchart of the sum of deaths versus the binned years. + +```R +data_source_subset = subset(data_source, data_source$Entity == "All natural disasters") + +chart_disasters = alt$Chart(data_source_subset)$ + mark_bar()$ + encode( + x = alt$X("Year:Q", bin = TRUE), + y = 'sum(Deaths):Q', + tooltip = 'sum(Deaths):Q' + ) +``` + +
+ + +
+ +Mind the difference in the syntax here. We used the long form `x = alt$X()` so that we can specify the binning inside encoding. Other adjustments can be related to scale or axis. + +
+ +{:.exercise} +**Exercise** - Check the documentation of the binning parameters [https://altair-viz.github.io/user_guide/generated/core/altair.BinParams.html](https://altair-viz.github.io/user_guide/generated/core/altair.BinParams.html) and increase the value of the maximum number of bins. + +
+ + +
+ +{:.exercise} +**Exercise** - Using `data_source_subset = subset(data_source, data_source$Entity != "All natural disasters")` make a heatmap that shows the count of disasters per year, like the one below. + +
+ +
+ + +
+ +Another filed transformation is the one that scales the original field domain to the custom range we specify. +For instance, we can transform a quantitative field using the log scale, as we can see below. + + +```R +chart_disasters = alt$Chart("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")$ + mark_bar()$encode( + x = 'Entity:N', + y = alt$Y('sum(Deaths):Q', scale=alt$Scale(type='log')) + )$properties( + height = 300, + width = 600 +) + +``` + +
+ + +
+ +Fortunately, not in all years from 1900 to 2017 all types of registered disasters occured. Did you notice that in 1904 there is no natural disaster registered? +Let's enrich the dataset in R with a variable for missing values based on the year. + +```R +data_source = read.csv(url("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")) # original data +Year = seq(1900, 2017, 1) # create year vector +Entity = sort(rep(unique(data_source$Entity), 118)) # create entity vector +data_mod = cbind.data.frame(Year, Entity) # create dataframe with complete set of year and entity +data_source_modified = merge(data_source, data_mod, by = c("Year", "Entity"), all = T) # merge df with original data +data_source_modified[is.na(data_source_modified$Deaths),"Deaths"] = 0 # replace NA with zero +data_source_modified$Missing = NULL # create new variable +data_source_modified[data_source_modified$Deaths == 0,"Missing"] = "1" # the value for missing +data_source_modified[data_source_modified$Deaths != 0,"Missing"] = "0" # the value for non-missing +str(data_source_modified) # look at the new data structure +rm(Year, Entity, data_mod) # remove objects that are not needed +``` + +Now we can plot the full time series, and specify a custom color scale for the presence of absence of the year in the data. +So, the domain of the data is `0` for Non-Missing, `1` for Missing and the custom range is the two colors of our preference, here black and red. + +```R +domain_color = c("0", "1") +range_color = c('black', 'red') + +data_source_subset = subset(data_source_modified, data_source_modified$Entity == "All natural disasters") + +chart_disasters = alt$Chart(data_source_subset)$ + mark_circle( + opacity = 0.8, + size = 50 + )$ + encode( + x = 'Year:O', + y = 'Deaths:Q', + color = alt$Color('Missing', scale = alt$Scale(domain = domain_color, range = range_color)), + tooltip = c("Year", "Deaths") + )$ + properties( + height = 300, + width = 600 + )$ + interactive() +``` + + +
+ + + + +{% include custom/series_vega-in-r_next.html %} diff --git a/pages/vega-in-r/layered-chart.md b/pages/vega-in-r/layered-chart.md new file mode 100644 index 0000000..d243c9a --- /dev/null +++ b/pages/vega-in-r/layered-chart.md @@ -0,0 +1,8000 @@ +--- +title: Layered chart +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-layered-chart.html +folder: vega-in-r +series: vega-in-r-series +weight: 7 +--- + +We are now looking at how we can combine charts in one canvas in altair R. + +First, we are discussing a layered chart example. Each chart can be made separately and combined uisng the `+` operator: `chart_layer_1 + chart_layer_2`. +Below, we make a chart that consists of a line layer and a point layer. The tooltip should be added to the top layer so that it is visible in the final chart. + +```R +chart_disasters_L1 = alt$Chart("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")$ + mark_line()$ + encode( + x = 'Year:O', + y = 'Deaths:Q' + )$ + transform_filter( + alt$FieldEqualPredicate(field = "Entity", equal = "All natural disasters") + )$ + properties( + height = 400, + width = 600 + ) + +chart_disasters_L2 = alt$Chart("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")$ + mark_point()$ + encode( + x = 'Year:O', + y = 'Deaths:Q', + tooltip = "Deaths:Q" + )$ + transform_filter( + alt$FieldEqualPredicate(field = "Entity", equal = "All natural disasters") + )$ + properties( + height = 400, + width = 600 + ) + +chart_disasters = (chart_disasters_L1 + chart_disasters_L2) +``` + + +
+ + +
+ +To produce the same chart we may also follow the procedure below. +Use the R code provided above for `chart_disasters_L2` and then make the first layer using: + +```R +chart_disasters_L1 = chart_disasters_L2$mark_line() +``` + +Then superimpose the charts as before: +```R +chart_disasters = (chart_disasters_L1 + chart_disasters_L2) +``` + +{:.exercise} +**Exercise** - Make a layered chart, which consists of one layer for the bar mark and one for the text mark, to produce the chart below. + + + +
+ + + +{% include custom/series_vega-in-r_next.html %} diff --git a/pages/vega-in-r/setting-things-up.md b/pages/vega-in-r/setting-things-up.md new file mode 100644 index 0000000..7f1a3cc --- /dev/null +++ b/pages/vega-in-r/setting-things-up.md @@ -0,0 +1,57 @@ +--- +title: Setting things up +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-setting-things-up.html +folder: vega-in-r +series: vega-in-r-series +weight: 1 +--- + +To get this tutorial started, we need, first, to install anaconda, and second, activate an r-reticulate environment using conda. We also need to install vega_datasets using pip and finally, install the R packages reticulate and altair using install.packages() in Rstudio. +Most of the steps described here are taken from [altair R installation](https://vegawidget.github.io/altair/articles/installation.html). + +After installing Anaconda, open the Anaconda Prompt. Update conda: +``` C +conda -V +conda update conda +```` + +Install the vega datasets that we will be used in this tutorial: +``` C +pip install vega_datasets +``` + +Next, create and activate a conda environmnet called `r-reticulate`: +``` C +conda create -n r-reticulate +conda activate r-reticulate +``` + +Open Rstudio IDE and install reticulate. Then, use the conda environment `r-reticulate`: +``` R +install.packages("reticulate") +reticulate::use_condaenv("r-reticulate") +``` + +Restart R studio and then install the altair package: +``` R +install.packages("altair") +``` + +In R studio, use the code below to install the Python packages altair and vega_datasets: +``` R +altair::install_altair() +``` + +Verify the installation using: +``` R +altair::check_altair() +``` + +The procedure described above should be run only in the beginning. The following times you want to use altair in Rstudio, you only need to call `library("altair")`. + + + + +{% include custom/series_vega-in-r_next.html %} diff --git a/pages/vega-in-r/simple-barchart.md b/pages/vega-in-r/simple-barchart.md new file mode 100644 index 0000000..d5467f4 --- /dev/null +++ b/pages/vega-in-r/simple-barchart.md @@ -0,0 +1,244 @@ +--- +title: A simple barchart +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-simple-barchart.html +folder: vega-in-r +series: vega-in-r-series +weight: 2 +--- +Here is a very simple barchart defined in altair R. + +
+ + +The dataset used for this chart is: + +```R +Var1 = c("a","b","c","d","e") +Var2 = c(11, 19, 22, 8, 14) +Var3 = c("type1","type1","type2","type1","type2") +dataset = data.frame(Var1, Var2, Var3) +``` + +and below is the code to generate it: + + +```R +chart_1 = + alt$Chart(dataset) + $mark_bar() + $encode( + x = "Var1:O", + y = "Var2:Q") + $properties( + height=200, + width=400 + ) +``` + +What is the syntax in altair R? It is similar to the altair Python with the major difference the usage of the operator `$` to access attributes, instead of `.`. We should note that there are some other differences of the Python and the R package described at the [Field Guide to Python Issues](https://vegawidget.github.io/altair/articles/field-guide-python.html) together with examples. +We should also notice that we use the object `alt` to access the Altair API and create a chart using `alt$Chart`. +- The `data` to be visualised is called inside the `alt$Chart`. +- The `mark` used is specifed after `mark_`. +- The `encode` determines the mapping between the channels and the data. Here, `x` and `y` are the position channels. The field type is specified after the field name. `O` stands for ordinal and `Q` for quantitative. The `x = "Var1:O"` is the short form of `x = alt$X("Var1", type = "ordinal")`. The two forms are equivalent but the long form is used when doing more adjustments unside encoding. We will see an example in the field transform section. +- The height and width of the plot is specified inside `properties`. + +To display the chart in Rstudio `vegawidget(chart_1)` or `chart_1` will not work. We can instead save the chart using: +```R +htmlwidgets::saveWidget(vegawidget(chart_1),'chart_1.html') +``` +and display it in the browser by opening the `chart_1.html` file. + +To examine the chart specification in R we can install the package listviewer using `install.packages("listviewer")` and use: +```R +vegawidget::vw_examine(chart_1, mode = "code") +``` +The output is below: +```R +{ + "$schema": "https://vega.github.io/schema/vega-lite/v4.0.0.json", + "config": { + "view": { + "continuousHeight": 300, + "continuousWidth": 400 + } + }, + "data": { + "name": "data-c15a74353a288269433adfdc7c0ad142" + }, + "datasets": { + "data-c15a74353a288269433adfdc7c0ad142": [ + { + "Var1": "a", + "Var2": 11, + "Var3": "type1" + }, + { + "Var1": "b", + "Var2": 19, + "Var3": "type1" + }, + { + "Var1": "c", + "Var2": 22, + "Var3": "type2" + }, + { + "Var1": "d", + "Var2": 8, + "Var3": "type1" + }, + { + "Var1": "e", + "Var2": 14, + "Var3": "type2" + } + ] + }, + "encoding": { + "x": { + "field": "Var1", + "type": "ordinal" + }, + "y": { + "field": "Var2", + "type": "quantitative" + } + }, + "height": 200, + "mark": "bar", + "width": 400 +} +``` + +{:.exercise} +**Exercise** - Make yourself comfortable with the basic syntax of the chart in the altair R. Use the color channel for `Var3` to make the chart below. Change the height and width of the panel. + + +
+ + + +{:.exercise} +**Exercise** - Visualise the same data, using a point as the mark, change the color for all points to black and visualise Var3 using size. Format the axes. + + + +{% include custom/series_vega-in-r_next.html %} diff --git a/pages/vega-in-r/simple-interaction.md b/pages/vega-in-r/simple-interaction.md new file mode 100644 index 0000000..289900f --- /dev/null +++ b/pages/vega-in-r/simple-interaction.md @@ -0,0 +1,191 @@ +--- +title: Simple Interaction +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-simple-interaction.html +folder: vega-in-r +series: vega-in-r-series +weight: 4 +--- + +One of the main advantages to use the altair package is the fact that supports the generation of interactive graphics. The code required for adding a simple interaction is relatively short. + +## Tooltip + +A tooltip can be added to the plot using `tooltip()` inside `encode()`. For one variable displayed in the tooltip we can use: + +```R +... +tooltip = "Variable_1:T" +... +``` + +and for more than one variable, we can use the R function `list()` or `c()` as illustrated below: + +```R +... +tooltip = c("Variable_1:T", "Variable_2:T") +... +``` + +Mind that if we are importing the data from a url directly in the plot specification, we may need to specify the field type. As shown above we may use ":T" for the type, where "T" may be `O` for orninal, `Q` for quantitative or `N` for nominal. Other types are `T` for temporal and `G` for goejson. + + +
+ + +{:.exercise} +**Exercise** - Add a tooltip in the heatmap we created in the previous section, to get the graph illustrated above. + + +## Zooming and Panning + +We illustrate two ways of making a graph zoomable and pannable. The first one is by adding the `intreactive()` attribute, as illustrated below: + +```R +chart = alt$Chart(data_source_subset)$ + ..... + $interactive() +``` + +A second option is to specify the selection outside the plot code and then use it inside the `add_selection` attribute in the chart code. +The second option is an interval selection using a scale binding. For more information on selection types supported in altair you can refer to [altair.selection_interval reference](https://altair-viz.github.io/user_guide/generated/api/altair.selection_interval.html#altair.selection_interval) + +```R +selection = alt$selection_interval(bind='scales') + +chart = alt$Chart(data_source_subset)$ +..... +$add_selection( + selection + ) +``` + +
+ + + +{:.exercise} +**Exercise** - Make the time series plot of all natural distasters interactive, to get the graph illustrated above. Use both ways of making it zoomable and pannable. + + +{% include custom/series_vega-in-r_next.html %} diff --git a/pages/vega-in-r/vega-in-r_landing_page.md b/pages/vega-in-r/vega-in-r_landing_page.md new file mode 100644 index 0000000..c30c5d6 --- /dev/null +++ b/pages/vega-in-r/vega-in-r_landing_page.md @@ -0,0 +1,25 @@ +--- +title: Vega in R +keywords: vega-in-r +sidebar: vega-in-r_sidebar +toc: false +permalink: vega-in-r_landing_page.html +folder: vega-in-r +series: vega-in-r-series +weight: 0 +--- + +![Rlogo]({{ site.baseurl }}/assets/cranR.PNG) + +In this tutorial, we will look into how to make visualisations in R using the Altair interface to Vega-Lite. +Altair in R uses the Reticulate framework to connect to Altair Python. While we go through this tutorial, please check the [altair R documentation](https://vegawidget.github.io/altair/index.html) as well as the [altair Python documentation](https://altair-viz.github.io/) + +Other useful sources are: +- [vegawidget R documentation](https://vegawidget.github.io/vegawidget/index.html) +- [R interface to Python](https://rstudio.github.io/reticulate/) +- [vega-lite documentation](https://vega.github.io/vega-lite/docs/) + + +For feedback or questions regararding the Vega in R tutorial, you may contact PhD candidate Danai Kafetzaki at danai.kafetzaki@kuleuven.be and Prof. Jan Aerts at jan.aerts@uhasselt.be. + +{% include custom/series_vega-in-r_next.html %} \ No newline at end of file diff --git a/pages/vega-in-r/widgets.md b/pages/vega-in-r/widgets.md new file mode 100644 index 0000000..6f4cb3a --- /dev/null +++ b/pages/vega-in-r/widgets.md @@ -0,0 +1,7343 @@ +--- +title: Using widgets for selection +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-widgets.html +folder: vega-in-r +series: vega-in-r-series +weight: 11 +--- + +We have seen how to select datapoints with brushing and linking. We are now looking at how to select datapoints based on a variable, using widgets. +In the example below, we make a layered time series chart in which we can select the natural disaster to be displayed form a dropdown list. In the default view, all time series are displayed. + +There are four steps to make this plot in altair R. +- First, we make a list of the elements that will be included in the dropdown selection, using conventional R code. We make sure that the elements of the list match the names of the variable we want to filter. +- Then, we create the chart, in the same way as we would make it if we have already filtered the data on one of the options included in the list above. +- In the third step, we make a dynamic query for the dropdown menu. To do so, we create a single element selection `entities_select`. We specify the name of the field we want to filter in `fields = list()`. We use the `binding_select` to specify the input options for the dynamic query. Last, we give a name for the widget. +- Finally, we modify the chart of step 2 by including the single selection we made in the previous step. We also include in the final chart a filter transform based on the dynamic query. + +```R +# step 1 +entities = list("Drought", "Earthquake", "Epidemic", "Extreme temperature", "Extreme weather", "Flood", "Landslide", "Mass movement (dry)", "Volcanic activity", "Wildfire") + +# step 2 +chart_a = alt$Chart(data_source_modified_subset)$ + mark_line()$ + encode( + x = "Year:O", + y = "Deaths:Q", + tooltip = c("Year:N","Deaths:Q") + )$ + properties( + height = 300, + width = 700 + ) + +chart_b = chart_a$mark_circle(size = 50)$encode(x = "Year:O", y = "Deaths:Q", color = "Missing:N") + +chart = chart_b + chart_a + +# step 3 +entities_select = alt$selection_single( + fields = list("Entity"), + bind = alt$binding_select(options = entities), + name = "Filter" + ) + +# step 4 +chart_filter_entities = chart$ + add_selection(entities_select)$ + transform_filter(entities_select) +``` + + + +
+ + + +
+ +For more information you may refer to the [reference for selection_single](https://altair-viz.github.io/user_guide/generated/api/altair.selection_single.html) and to the [guide on binding](https://altair-viz.github.io/user_guide/interactions.html#binding-adding-data-driven-inputs) +The [vega-lite documentation for selections](https://vega.github.io/vega-lite/docs/selection.html) may also be useful. + +
+ +{:.exercise} +**Exercise** - Make a normalized stacked area chart of Deaths versus Year for `Epidemic`, `Extreme temperature`, `Extreme weather` and `Flood`. Include a radio button that allow you to highlight one type of disaster at a time. The end result should look like the chart below. Hint: Use `binding_radio`. + + +
+ + + + +{% include custom/series_vega-in-r_next.html %} From 3c4cd0ab0041017819e69b350caee6a5ee073176 Mon Sep 17 00:00:00 2001 From: Danai Kafetzaki Date: Tue, 31 Mar 2020 21:02:35 +0200 Subject: [PATCH 03/17] Add files via upload --- _data/topnav.yml | 43 +++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/_data/topnav.yml b/_data/topnav.yml index 63a6b76..e142883 100644 --- a/_data/topnav.yml +++ b/_data/topnav.yml @@ -1,20 +1,23 @@ -## Topnav single links -## if you want to list an external url, use external_url instead of url. the theme will apply a different link base. -topnav: -- title: Topnav - items: - - title: GitHub - external_url: https://github.com/vda-lab/visualisation-tutorial - -#Topnav dropdowns -topnav_dropdowns: -- title: Topnav dropdowns - folders: - - title: Tutorials - folderitems: - - title: Vega-lite - url: /vegalite_landing_page.html - - title: Vega - url: /vega_landing_page.html - - title: HoloViz - url: /holoviz_landing_page.html +## Topnav single links +## if you want to list an external url, use external_url instead of url. the theme will apply a different link base. +topnav: +- title: Topnav + items: + - title: GitHub + external_url: https://github.com/vda-lab/visualisation-tutorial + +#Topnav dropdowns +topnav_dropdowns: +- title: Topnav dropdowns + folders: + - title: Tutorials + folderitems: + - title: Vega-lite + url: /vegalite_landing_page.html + - title: Vega + url: /vega_landing_page.html + - title: HoloViz + url: /holoviz_landing_page.html + - title: Vega in R + url: /vega-in-r_landing_page.html + From 0e664d85f9caceffe26589a0f6d22dc222e0ebb9 Mon Sep 17 00:00:00 2001 From: Danai Kafetzaki Date: Tue, 31 Mar 2020 21:03:17 +0200 Subject: [PATCH 04/17] Add files via upload --- _data/sidebars/home_sidebar.yml | 41 ++++++++------- _data/sidebars/vega-in-r_sidebar.yml | 79 ++++++++++++++++++++++++++++ 2 files changed, 101 insertions(+), 19 deletions(-) create mode 100644 _data/sidebars/vega-in-r_sidebar.yml diff --git a/_data/sidebars/home_sidebar.yml b/_data/sidebars/home_sidebar.yml index 0af4ed1..79089a7 100644 --- a/_data/sidebars/home_sidebar.yml +++ b/_data/sidebars/home_sidebar.yml @@ -1,19 +1,22 @@ -# This is your sidebar TOC. The sidebar code loops through sections here and provides the appropriate formatting. - -entries: -- title: Sidebar - levels: one - folders: - - - title: Tutorials - output: web - folderitems: - - title: Vega-Lite - url: /vegalite_landing_page.html - output: web - - title: Vega - url: /vega_landing_page.html - output: web - - title: HoloViz - url: /holoviz_landing_page.html - output: web +# This is your sidebar TOC. The sidebar code loops through sections here and provides the appropriate formatting. + +entries: +- title: Sidebar + levels: one + folders: + + - title: Tutorials + output: web + folderitems: + - title: Vega-Lite + url: /vegalite_landing_page.html + output: web + - title: Vega + url: /vega_landing_page.html + output: web + - title: HoloViz + url: /holoviz_landing_page.html + output: web + - title: Vega in R + url: /vega-in-r_landing_page.html + output: web diff --git a/_data/sidebars/vega-in-r_sidebar.yml b/_data/sidebars/vega-in-r_sidebar.yml new file mode 100644 index 0000000..9b6df26 --- /dev/null +++ b/_data/sidebars/vega-in-r_sidebar.yml @@ -0,0 +1,79 @@ +entries: +- title: sidebar + product: Vega in R tutorial + folders: + + - title: + output: pdf + type: frontmatter + folderitems: + - title: + url: /titlepage.html + output: pdf + type: frontmatter + - title: + url: /tocpage.html + output: pdf + type: frontmatter + + - title: Vega in R landing page + output: web, pdf + folderitems: + - title: Vega in R landing page + url: /vega-in-r_landing_page.html + output: web, pdf + - title: Setting things up + url: /vega-in-r-setting-things-up.html + output: web, pdf + - title: Creating static images + output: web, pdf + folderitems: + - title: A simple barchart + url: /vega-in-r-simple-barchart.html + output: web, pdf + - title: Changing the data + url: /vega-in-r-changing-data.html + output: web, pdf + - title: Simple Interaction + output: web, pdf + folderitems: + - title: Simple interaction + url: /vega-in-r-simple-interaction.html + output: web, pdf + - title: Transforms + output: web, pdf + folderitems: + - title: Field transform + url: /vega-in-r-field-transform.html + output: web, pdf + - title: Data transform + url: /vega-in-r-data-transformations.html + output: web, pdf + - title: Combine Charts + output: web, pdf + folderitems: + - title: Layered chart + url: /vega-in-r-layered-chart.html + output: web, pdf + - title: Concatenated chart + url: /vega-in-r-concatenated-chart.html + output: web, pdf + - title: Faceted chart + url: /vega-in-r-faceted-chart.html + output: web, pdf + - title: Brush and link + output: web, pdf + folderitems: + - title: Brush and link + url: /vega-in-r-brush-and-link.html + output: web, pdf + - title: Widgets + output: web, pdf + folderitems: + - title: Widgets for selections + url: /vega-in-r-widgets.html + output: web, pdf + + + + From 2c4be2be09afd405bdc59f86b3cac100ba58364e Mon Sep 17 00:00:00 2001 From: Danai Kafetzaki Date: Tue, 31 Mar 2020 21:03:39 +0200 Subject: [PATCH 05/17] Add files via upload --- index.md | 133 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 67 insertions(+), 66 deletions(-) diff --git a/index.md b/index.md index efd10b7..86c0e9d 100644 --- a/index.md +++ b/index.md @@ -1,66 +1,67 @@ ---- -title: "Data Visualisation in Data Science" -keywords: homepage -permalink: index.html ---- -![]({{ site.baseurl }}/assets/stad_airquality.jpeg) - -Welcome to this set of tutorials for data visualisation. These were created to serve as teaching material for the EBI workshop [Data Visualisation for Biology: A Practical Workshop on Design, Techniques and Tools](https://www.ebi.ac.uk/training/events/2020/data-visualisation-biology-practical-workshop-design-techniques-and-tools-1) as well as the course material for the Data Visualisation for Data Science courses at [UHasselt](https://www.uhasselt.be/studiegids?n=4&a=2019&i=4142) and [KU Leuven](https://onderwijsaanbod.kuleuven.be/syllabi/e/G0R72AE.htm#activetab=doelstellingen_idm480336). - -The contents of these tutorials is licensed as CC-BY: feel free to copy/remix/tweak/... it, but please credit your source. - -![CC-BY]({{ site.baseurl }}/assets/ccby.png) - -In these tutorial, we will work in different phases, looking at vega-lite, vega, and Holoviz. We'll start with vega-lite and vega in the [online editor](https://vega.github.io/editor/) that they provide, and move on to using HoloViz at a later stage. - -This tutorial is based on material provided on the vega-lite, vega and holoviz websites, as well as teaching material collected by Ryo Sakai. - -## Preamble -### What are vega-lite and vega? -You might have heard of [D3](http://d3js.org) as a library to create interactive data visualisations. Indeed, this library is considered the standard in the field. Unfortunately, it does have quite a steep learning curve which makes it not ideal if you have to learn it in 2-3 days without a background in javascript programming. In this course, we'll use vega and vega-lite instead. Both are so-called _declarative_ languages, where you tell the computer _what_ you need, not _how_ to do it. Vega and vega-lite are expressed in _JSON_ ("javascript object notation"). - -This image by [Eric Marty](https://blog.ericmarty.com/the-d3-/-vega-stack) provides a good overview how D3, vega and vega-lite are related: - - - -To give you an idea, here's a small vega-lite script that shows a barchart. - -```json -{ - "$schema": "https://vega.github.io/schema/vega-lite/v4.json", - "data": { - "values": [ - {"a": "A", "b": 28}, {"a": "B", "b": 55}, {"a": "C", "b": 43} - ] - }, - "mark": "bar", - "encoding": { - "x": {"field": "b", "type": "quantitative"}, - "y": {"field": "a", "type": "ordinal"} - } -} -``` - -The resulting barchart: - - - -### JSON -The above code is nothing more than a JSON (JavaScript Object Notation) data structure. It is similar to XML, but more readable: - -- strings are put between double quotes `"` -- numbers are _not_ put between quotes -- lists (aka arrays) are put between square brackets `[]` -- objects (aka hashes, aka dictionaries, aka key-value pairs) are put between curly brackets `{}`, and key and value are separated with a colon `:` - -Also, these objects can be nested. In the example above, the whole thing is a single JSON object, consisting of key-value pairs (keys being `"$schema"`, `"data"`, `"mark"` and `"encoding"`). The `"data"` key itself holds an object `{ "values": [ ... ]}`. The `"values"` key in its place is an array of objects again. - -Different elements in a JSON object or array have to be separated by a comma `,`. - -That's the preamble finished. Let's start with... - -## The actual tutorials - -* [Vega-Lite]({{ site.baseurl }}/vegalite_landing_page.html) -* [Vega]({{ site.baseurl }}/vega_landing_page.html) -* [Holoviz]({{ site.baseurl }}/holoviz_landing_page.html) +--- +title: "Data Visualisation in Data Science" +keywords: homepage +permalink: index.html +--- +![]({{ site.baseurl }}/assets/stad_airquality.jpeg) + +Welcome to this set of tutorials for data visualisation. These were created to serve as teaching material for the EBI workshop [Data Visualisation for Biology: A Practical Workshop on Design, Techniques and Tools](https://www.ebi.ac.uk/training/events/2020/data-visualisation-biology-practical-workshop-design-techniques-and-tools-1) as well as the course material for the Data Visualisation for Data Science courses at [UHasselt](https://www.uhasselt.be/studiegids?n=4&a=2019&i=4142) and [KU Leuven](https://onderwijsaanbod.kuleuven.be/syllabi/e/G0R72AE.htm#activetab=doelstellingen_idm480336). + +The contents of these tutorials is licensed as CC-BY: feel free to copy/remix/tweak/... it, but please credit your source. + +![CC-BY]({{ site.baseurl }}/assets/ccby.png) + +In these tutorial, we will work in different phases, looking at vega-lite, vega, and Holoviz. We'll start with vega-lite and vega in the [online editor](https://vega.github.io/editor/) that they provide, and move on to using HoloViz at a later stage. + +This tutorial is based on material provided on the vega-lite, vega and holoviz websites, as well as teaching material collected by Ryo Sakai. + +## Preamble +### What are vega-lite and vega? +You might have heard of [D3](http://d3js.org) as a library to create interactive data visualisations. Indeed, this library is considered the standard in the field. Unfortunately, it does have quite a steep learning curve which makes it not ideal if you have to learn it in 2-3 days without a background in javascript programming. In this course, we'll use vega and vega-lite instead. Both are so-called _declarative_ languages, where you tell the computer _what_ you need, not _how_ to do it. Vega and vega-lite are expressed in _JSON_ ("javascript object notation"). + +This image by [Eric Marty](https://blog.ericmarty.com/the-d3-/-vega-stack) provides a good overview how D3, vega and vega-lite are related: + + + +To give you an idea, here's a small vega-lite script that shows a barchart. + +```json +{ + "$schema": "https://vega.github.io/schema/vega-lite/v4.json", + "data": { + "values": [ + {"a": "A", "b": 28}, {"a": "B", "b": 55}, {"a": "C", "b": 43} + ] + }, + "mark": "bar", + "encoding": { + "x": {"field": "b", "type": "quantitative"}, + "y": {"field": "a", "type": "ordinal"} + } +} +``` + +The resulting barchart: + + + +### JSON +The above code is nothing more than a JSON (JavaScript Object Notation) data structure. It is similar to XML, but more readable: + +- strings are put between double quotes `"` +- numbers are _not_ put between quotes +- lists (aka arrays) are put between square brackets `[]` +- objects (aka hashes, aka dictionaries, aka key-value pairs) are put between curly brackets `{}`, and key and value are separated with a colon `:` + +Also, these objects can be nested. In the example above, the whole thing is a single JSON object, consisting of key-value pairs (keys being `"$schema"`, `"data"`, `"mark"` and `"encoding"`). The `"data"` key itself holds an object `{ "values": [ ... ]}`. The `"values"` key in its place is an array of objects again. + +Different elements in a JSON object or array have to be separated by a comma `,`. + +That's the preamble finished. Let's start with... + +## The actual tutorials + +* [Vega-Lite]({{ site.baseurl }}/vegalite_landing_page.html) +* [Vega]({{ site.baseurl }}/vega_landing_page.html) +* [Holoviz]({{ site.baseurl }}/holoviz_landing_page.html) +* [Vega in R]({{ site.baseurl }}/vega-in-r_landing_page.html) From 1e2e96cbb4d78895233ba53aaae9e674a40b3992 Mon Sep 17 00:00:00 2001 From: Danai Kafetzaki Date: Tue, 31 Mar 2020 21:04:01 +0200 Subject: [PATCH 06/17] Add files via upload --- assets/cranR.PNG | Bin 0 -> 6625 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 assets/cranR.PNG diff --git a/assets/cranR.PNG b/assets/cranR.PNG new file mode 100644 index 0000000000000000000000000000000000000000..07fa2de5a57c758d504eafb67615cbd2482cead8 GIT binary patch literal 6625 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 ZOB^HU^aols@L7h#)X2iH{Hpu?{{c-VF7yBZ literal 0 HcmV?d00001 From 91460ac2d8d56c14e3e4f3808e48f52f665a9c67 Mon Sep 17 00:00:00 2001 From: Danai Kafetzaki Date: Wed, 1 Apr 2020 11:22:30 +0200 Subject: [PATCH 07/17] Delete 1_setting-things-up.md --- pages/vega-in-r/1_setting-things-up.md | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 pages/vega-in-r/1_setting-things-up.md diff --git a/pages/vega-in-r/1_setting-things-up.md b/pages/vega-in-r/1_setting-things-up.md deleted file mode 100644 index 86ecad2..0000000 --- a/pages/vega-in-r/1_setting-things-up.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: Setting things up -keywords: vega-in-r -sidebar: vega-in-r_sidebar -permalink: /vega-in-r-a-simple-barchart.html -folder: vega-in-r -series: vega-in-r-series -weight: 1 ---- - -Setting things up - to be updated... - -{% include custom/series_vega-in-r_next.html %} From 71f0e58d7d5941a144143031c1aca25e4059b679 Mon Sep 17 00:00:00 2001 From: Danai Kafetzaki Date: Wed, 1 Apr 2020 11:22:42 +0200 Subject: [PATCH 08/17] Delete 2_simple-barchart.md --- pages/vega-in-r/2_simple-barchart.md | 175 --------------------------- 1 file changed, 175 deletions(-) delete mode 100644 pages/vega-in-r/2_simple-barchart.md diff --git a/pages/vega-in-r/2_simple-barchart.md b/pages/vega-in-r/2_simple-barchart.md deleted file mode 100644 index 82787e0..0000000 --- a/pages/vega-in-r/2_simple-barchart.md +++ /dev/null @@ -1,175 +0,0 @@ ---- -title: A simple barchart -keywords: vega-in-r -sidebar: vega-in-r_sidebar -permalink: /vega-in-r-a-simple-barchart.html -folder: vega-in-r -series: vega-in-r-series -weight: 2 ---- -Here is a very simple barchart defined in altair in R. - -
- - -The dataset of the chart is: - -```R -Var1 = c("a","b","c","d","e") -Var2 = c(11, 19, 22, 8, 14) -Var3 = c("type1","type1","type2","type1","type2") -dataset = data.frame(Var1, Var2, Var3) -``` - -and below is the code used to generate it: - - -```R -chart_1 = - alt$Chart(dataset)$ - mark_bar()$ - encode( - x = "Var1:O", - y = "Var2:Q" - # color = "Var3:N" - )$properties( - height=200, - width=400 - ) -``` - -What is the syntax in the altair R? It is similar to the Python altair and the major difference is the usage of the operator `$` to access attributes, instead of `.`. -We use the object `alt` to access the Altair API and the first basic argument is the `alt$Chart`. -- The `data` to be visualised is called inside the `alt$Chart`. -- The `mark` is specifed after `mark_`. -- The `encoding` determines the mapping between the channels and the data. Here, `x` and `y` are the position channels. The field type is specified after the field name. `O` stands for ordinal and `Q` for quantitative. -- The height and width of the plot is specified inside `properties`. - - -{:.exercise} -**Exercise** - Make yourself comfortable with the syntax of this basic altair chart. Use the color channel for `Var3` to make the chart below. Then, change the mark and add a variable for size. - -
- - -{:.exercise} -**Exercise** - Change the height and width of the panel and remake the plot above. - - -{% include custom/series_vega-in-r_next.html %} From 30933d0996d0f34f2a5205b51fb3096c11261b28 Mon Sep 17 00:00:00 2001 From: Danai Kafetzaki Date: Wed, 1 Apr 2020 11:23:24 +0200 Subject: [PATCH 09/17] Delete 3_changing-data.md --- pages/vega-in-r/3_changing-data.md | 257 ----------------------------- 1 file changed, 257 deletions(-) delete mode 100644 pages/vega-in-r/3_changing-data.md diff --git a/pages/vega-in-r/3_changing-data.md b/pages/vega-in-r/3_changing-data.md deleted file mode 100644 index 63e04bc..0000000 --- a/pages/vega-in-r/3_changing-data.md +++ /dev/null @@ -1,257 +0,0 @@ ---- -title: A case study -keywords: vega-in-r -sidebar: vega-in-r_sidebar -permalink: /vega-in-r-a-case-study.html -folder: vega-in-r -series: vega-in-r-series -weight: 3 ---- -Let's now use a more realistic example and visualize the natural diasters dataset [https://ourworldindata.org/natural-disasters.html](https://ourworldindata.org/natural-disasters.html). -This dataset is included in the vega_datasets package [https://github.com/vega/vega-datasets.html] (https://github.com/vega/vega-datasets.html). - -You can import the datasets using the altair library. -vega_data = altair::import_vega_data() - -See the list of the available datasets -```R -vega_data$list_datasets() -``` - -and select the one you want to visualise. -```R -data_source = vega_data$disasters() -``` - -Alternatively, you may read the data from a url using: -```R -data_source = read.csv(url("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")) -``` - -or load the data from a local file using standard R code. - -After importing the data, we can take a first look using standard R code: - -```R -str(data_source) -summary(data_source) -head(data_source); tail(data_source) -``` - -We can now make a plot similar to the one at [https://altair-viz.github.io/gallery/natural_disasters.html](https://altair-viz.github.io/gallery/natural_disasters.html) -For now, we may filter tha data in R and use the subset of the data to make the plot in altair R. On the data transformations section we will see how to do the filtering inside the altair specification. - -
- - - -Below is the code to make this plot. - -```R -data_source_subset = subset(data_source, data_source$Entity != "All natural disasters") - -chart_disasters = - alt$Chart(data_source_subset)$ - mark_circle( - opacity=0.8, - stroke='black', - strokeWidth=1 - )$ - encode( - x = "Year:O", - y = "Entity:N", - color = "Entity:N", - size = "Deaths:Q" - )$properties( - height=200, - width=400 - ) -``` -The global properties of the circles are specified inside the mark attribute and the properties that depend on the data inside the encoding. -Using the mark type `rect` with `color` and `opacity` channels we can make a heatmap plot. - - -```R -chart_disasters = - alt$Chart(data_source_subset)$ - mark_circle( - opacity=0.8, - stroke='black', - strokeWidth=1 - )$ - encode( - x = "Year:O", - y = "Entity:N", - color = "Entity:N", - size = "Deaths:Q" - )$properties( - height=200, - width=400 - ) -``` - - -
- - -Next, using the code below, we can make a time series plot of deaths from all natural disasters from 1900 until 2017. - -```R -data_source_subset = subset(data_source, data_source$Entity == "All natural disasters") - -chart_disasters = alt$Chart(data_source_subset)$ - mark_line()$ - encode( - x='Year:Q', - y='Deaths:Q', - tooltip = c("Year", "Deaths") - )$properties( - height=300, - width=600 -) -``` - -
- - - -{:.exercise} -**Exercise** - Use the `color` channel to make a time series plot per Entity. - -{:.exercise} -**Exercise** - Change the field types. What is the result? - -{:.exercise} -**Exercise** - Make a barchart for total deaths per Entity. Hint: You may do the calculation in R or try a calculation inside encoding. - - -{% include custom/series_vega-in-r_next.html %} From 9c64de1639f4c898287ac1143a0c65eeb3b50ea3 Mon Sep 17 00:00:00 2001 From: Danai Kafetzaki Date: Wed, 1 Apr 2020 11:23:36 +0200 Subject: [PATCH 10/17] Delete 4_simple-interaction.md --- pages/vega-in-r/4_simple-interaction.md | 192 ------------------------ 1 file changed, 192 deletions(-) delete mode 100644 pages/vega-in-r/4_simple-interaction.md diff --git a/pages/vega-in-r/4_simple-interaction.md b/pages/vega-in-r/4_simple-interaction.md deleted file mode 100644 index 21935a5..0000000 --- a/pages/vega-in-r/4_simple-interaction.md +++ /dev/null @@ -1,192 +0,0 @@ ---- -title: Simple Interaction -keywords: vega-in-r -sidebar: vega-in-r_sidebar -permalink: /vega-in-r-simple-interaction.html -folder: vega-in-r -series: vega-in-r-series -weight: 4 ---- - -One of the main advantages to use the altair package is the fact that supports the generation of interactive graphics. The code required for adding a simple interaction is relatively short. - -# Tooltip - -A tooltip can be added to the plot using `tooltip()` inside encode. For one variable displayed in the tooltip we can use: - -```R -... -tooltip = "Variable_1" -... -``` - -and for more than one variable, we can use the R function c() as illustrated below: - -```R -... -tooltip = c("Variable_1", "Variable_2") -... -``` - -Mind that if you are importing the data from a url directly in the plot specification, you may need to specify the field type. - - -
- - -{:.exercise} -**Exercise** - Add a tooltip in the heatmap we created in the previous section, to get the graph illustrated above. - - -# Zooming and Panning - -We illustrate two ways of making a graph zoomable and pannable. The first one is by adding the `intreactive()` attribute, as illustrated below: - -```R -$interactive() -``` - -A second option is to specify the selection outside the plot code and then use it inside the `add_selection` attribute in the chart code. -The second option is an interval selection using a scale binding. - -```R -selection = alt$selection_interval(bind='scales') - -chart = alt$Chart(data_source_subset)$ -..... -$add_selection( - selection - ) -``` - -
- - - -{:.exercise} -**Exercise** - Make the time series plot of all natural distasters interactive, to get the graph illustrated above. Use both ways of making it zoomable and pannable. - -{:.exercise} -**Exercise** - Go through the other selection types supported in altair. [https://altair-viz.github.io/user_guide/generated/api/altair.selection_interval.html#altair.selection_interval.html](https://altair-viz.github.io/user_guide/generated/api/altair.selection_interval.html#altair.selection_interval) - - -{% include custom/series_vega-in-r_next.html %} From 497bc5f47445f3265c2d3ec39072849b812e0d41 Mon Sep 17 00:00:00 2001 From: Danai Kafetzaki Date: Wed, 1 Apr 2020 11:23:48 +0200 Subject: [PATCH 11/17] Delete 5_field-transform.md --- pages/vega-in-r/5_field-transform.md | 1080 -------------------------- 1 file changed, 1080 deletions(-) delete mode 100644 pages/vega-in-r/5_field-transform.md diff --git a/pages/vega-in-r/5_field-transform.md b/pages/vega-in-r/5_field-transform.md deleted file mode 100644 index a8332ad..0000000 --- a/pages/vega-in-r/5_field-transform.md +++ /dev/null @@ -1,1080 +0,0 @@ ---- -title: Field Transform -keywords: vega-in-r -sidebar: vega-in-r_sidebar -permalink: /vega-in-r-field-transform.html -folder: vega-in-r -series: vega-in-r-series -weight: 5 ---- - -Since we are wokring in R, we can modify the data outside the plot specification and then use the modified dataset inside the plot encoding. -However, using the altair package, calculations inside the plot specification can be sometimes easier. In this section, we are discussing field trasforms that can be done inside encoding. -As we have seen from the beginning of this tutorial, the `encoding` determines the mapping between the channels and the data. We have already used encoding channels such as position channels `x` and `y` and mark property channels, for instance, `color` and `opacity`. -We only need to add `bin = TRUE` in the `x` position channel of a quantitative field to use the binned version of the field in the plot. -Below, there is the code to produce a barchart of the sum of deaths versus the binned years. - -```R -data_source_subset = subset(data_source, data_source$Entity == "All natural disasters") - -chart_disasters = alt$Chart(data_source_subset)$ - mark_bar()$ - encode( - alt$X("Year:Q", bin = TRUE), - y='sum(Deaths):Q', - tooltip = 'sum(Deaths):Q' -) -``` - -
- - -{:.exercise} -**Exercise** - Check the documentation of the binning parameters [https://altair-viz.github.io/user_guide/generated/core/altair.BinParams.html](https://altair-viz.github.io/user_guide/generated/core/altair.BinParams.html) and increase the value of the maximum number of bins. - -
- - - -{:.exercise} -**Exercise** - Using `data_source_subset = subset(data_source, data_source$Entity != "All natural disasters")` make a line plot that shows the deaths from all natural disasters versus time. - -{:.exercise} -**Exercise** - Using `data_source_subset = subset(data_source, data_source$Entity != "All natural disasters")` make a heatmap that shows the count of disasters per year, like the one below. - - -
- - - -Another filed transformation is the one that scales the original field domain to the range we specify. -For instance, we can transform a quantitative field using the log scale. - - -```R -chart_disasters = alt$Chart("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")$ - mark_bar()$encode( - x = 'Entity:N', - alt$Y('sum(Deaths):Q', scale=alt$Scale(type='log')) - )$properties( - height=300, - width=600 -) - -``` - -
- - - -Fortunately, not in all years from 1900 to 2017 all types of registered disasters occured. Did you notice that in 1904 there is no natural disaster registered? -Let's enrich the dataset in R with a variable for missing values based on the year. - -```R -data_source = read.csv(url("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")) # original data -Year = seq(1900, 2017, 1) # create year vector -Entity = sort(rep(unique(data_source$Entity), 118)) # create entity vector -data_mod = cbind.data.frame(Year, Entity) # create dataframe with complete set of year and entity -data_source_modified = merge(data_source, data_mod, by = c("Year", "Entity"), all = T) # merge df with original data -data_source_modified[is.na(data_source_modified$Deaths),"Deaths"] = 0 # replace NA with zero -data_source_modified$Missing = NULL # create new variable -data_source_modified[data_source_modified$Deaths == 0,"Missing"] = "1" # the value for missing -data_source_modified[data_source_modified$Deaths != 0,"Missing"] = "0" # the value for non-missing -str(data_source_modified) # look at the new data structure -rm(Year, Entity, data_mod) # remove objects that are not needed -``` - -Now we can plot the full time series, and specify a custom color scale for the presence of absence of the year in the data. -So, the domain of the data is `0` and `1` and the custom range is the two colors of our preference. - -```R -domain_color = c("0", "1") -range_color = c('black', 'red') - -data_source_subset = subset(data_source_modified, data_source_modified$Entity == "All natural disasters") - -chart_disasters = alt$Chart(data_source_subset)$ - mark_circle( - opacity=0.8, - size = 50 - )$ - encode( - x='Year:O', - y='Deaths:Q', - color=alt$Color('Missing', scale=alt$Scale(domain=domain_color, range=range_color)), - tooltip = c("Year", "Deaths") - )$properties( - height=300, - width=600 - )$ - interactive() -``` - - -
- - - - -{% include custom/series_vega-in-r_next.html %} From 83e8378012470ce29613d29030999834fa9c7d52 Mon Sep 17 00:00:00 2001 From: Danai Kafetzaki Date: Wed, 1 Apr 2020 11:23:58 +0200 Subject: [PATCH 12/17] Delete 6_data-transformations.md --- pages/vega-in-r/6_data-transformations.md | 194 ---------------------- 1 file changed, 194 deletions(-) delete mode 100644 pages/vega-in-r/6_data-transformations.md diff --git a/pages/vega-in-r/6_data-transformations.md b/pages/vega-in-r/6_data-transformations.md deleted file mode 100644 index e775d46..0000000 --- a/pages/vega-in-r/6_data-transformations.md +++ /dev/null @@ -1,194 +0,0 @@ ---- -title: Data Transformations -keywords: vega-in-r -sidebar: vega-in-r_sidebar -permalink: /vega-in-r-data-transformations.html -folder: vega-in-r -series: vega-in-r-series -weight: 6 ---- - -As mentioned in the documentation of altair, [https://altair-viz.github.io/user_guide/transform/index.html](https://altair-viz.github.io/user_guide/transform/index.html) in most cases, it is suggested to perform transformations outside the chart definition, so in our case using R. Of course, data transforms inside the chart can also be useful in some cases. -So far, we have been filtering the data in R and then using the modified data in the chart specification. Now, we use the `transform_filter()` to subset the data inside the chart. We make the linechart we have seen in a previous section using the code below: - -```R -chart_disasters = alt$Chart("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")$ - mark_line()$ - encode( - x='Year:Q', - y='Deaths:Q', - tooltip = c("Year", "Deaths") - )$properties( - height=300, - width=600 - )$transform_filter( - alt$FieldEqualPredicate(field = "Entity", equal = "All natural disasters") -) -``` - -
- - - -{:.exercise} -**Exercise** - Use the filter transform to obtain the data related to volcanic activity and earthquake and make an area chart like the one below. Hint: Go through the documentation for Field Predicates at [https://altair-viz.github.io/user_guide/transform/filter.html#user-guide-filter-transform](https://altair-viz.github.io/user_guide/transform/filter.html#user-guide-filter-transform). - -
- - -We now also use the `transform_window()` to compute and plot a windowed aggregation of the deaths over all available years. - - -```R -chart_disasters = alt$Chart("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")$ - transform_window( - cumulative_count='sum(Deaths)' -)$mark_area()$encode( - x='Year:O', - y='cumulative_count:Q', - tooltip = c("Year:Q", 'cumulative_count:Q') -)$transform_filter( - alt$FieldEqualPredicate(field = "Entity", equal = "All natural disasters") -)$properties( - height=300, - width=600 -) -``` - -
- - - - -{% include custom/series_vega-in-r_next.html %} From d088ab19ae1aa7c5cf5e013bf099baa74a2781db Mon Sep 17 00:00:00 2001 From: Danai Kafetzaki Date: Wed, 1 Apr 2020 11:25:16 +0200 Subject: [PATCH 13/17] Delete installation.md --- pages/vega-in-r/installation.md | 84 --------------------------------- 1 file changed, 84 deletions(-) delete mode 100644 pages/vega-in-r/installation.md diff --git a/pages/vega-in-r/installation.md b/pages/vega-in-r/installation.md deleted file mode 100644 index c50f57c..0000000 --- a/pages/vega-in-r/installation.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: Installation -keywords: vega-in-r -sidebar: vega-in-r_sidebar -permalink: /vega-in-r-installation.html -folder: vega-in-r -series: vega-in-r-series -weight: 1 ---- -We've now seen how to do brushing and linking across different plots. One of the typical use cases is the scatterplot matrix. Based on what we've seen above, we can already create this, just by adding specifications to the `concat` section. - -{:.exercise} -**Exercise** - Create a scatterplot matrix of the features `Weight_in_lbs`, `Miles_per_Gallon` and `Acceleration` with linking and brushing as we did above. - -When doing the exercise, you'll notice that there is a lot of repetition, as the `selection`, `marks` and `encoding` are repeated for each plot. For this use case, vega-lite provides the `repeat` keyword. It allows you to extract the variable part of the specification into a separate array. When you do this, you'll have to put the `selection`, `marks` and `encoding` within a separate `spec` again. - -```json -{ - "$schema": "https://vega.github.io/schema/vega-lite/v4.json", - "title": "Scatterplot matrix", - "data": { - "url": "https://raw.githubusercontent.com/vega/vega/master/docs/data/cars.json" - }, - "repeat": { - "column": [ "Weight_in_lbs", "Miles_per_Gallon", "Acceleration" ], - "row": [ "Weight_in_lbs", "Miles_per_Gallon", "Acceleration" ] - }, - "spec": { - "selection": { - "my_selection": {"type": "interval", "empty": "none"} - }, - "mark": "circle", - "encoding": { - "x": {"field": {"repeat": "column"}, "type": "quantitative"}, - "y": {"field": {"repeat": "row"}, "type": "quantitative"}, - "color": { - "condition": { - "selection": "my_selection", - "value": "red" - }, - "value": "lightgrey" - } - } - } -} -``` - -This will give you this image. Try selecting a group of datapoints. - -
- - - -{% include custom/series_vega-in-r_next.html %} From c33b3e411766f6159dd64c7bbbf332239500762e Mon Sep 17 00:00:00 2001 From: Danai Kafetzaki Date: Wed, 1 Apr 2020 21:10:57 +0200 Subject: [PATCH 14/17] Add files via upload --- pages/vega-in-r/brush-and-link.md | 4 +- pages/vega-in-r/changing-data.md | 15 ++--- pages/vega-in-r/data-transformations.md | 2 +- pages/vega-in-r/field-transform.md | 37 ++++++++---- pages/vega-in-r/setting-things-up.md | 4 +- pages/vega-in-r/simple-barchart.md | 75 ++++--------------------- pages/vega-in-r/simple-interaction.md | 2 +- 7 files changed, 48 insertions(+), 91 deletions(-) diff --git a/pages/vega-in-r/brush-and-link.md b/pages/vega-in-r/brush-and-link.md index a028b84..ba2dda7 100644 --- a/pages/vega-in-r/brush-and-link.md +++ b/pages/vega-in-r/brush-and-link.md @@ -7185,7 +7185,7 @@ If we now make a second chart that inherits all the properties of the first char chart_2a = chart_1$properties(width = 300, height = 300) chart_2b = chart_2a$encode(x = "Entity:N") -chart_distasters = (chart_2a | chart_2b) +chart_disasters = (chart_2a | chart_2b) ```
@@ -14358,7 +14358,7 @@ chart_distasters = (chart_2a | chart_2b)
{:.exercise} -**Exercise** - Make a one-way brushable and linkable chart of the deaths versus time per entity. The interval selection appears in a barchart below. +**Exercise** - Make a one-way brushable and linkable chart of the deaths versus time per entity. The interval selection appears in a barchart below. Hint: Check the [altair R gallery of interactive charts](https://vegawidget.github.io/altair/articles/example-gallery-08-interactive-charts.html)
diff --git a/pages/vega-in-r/changing-data.md b/pages/vega-in-r/changing-data.md index aefa001..df4c141 100644 --- a/pages/vega-in-r/changing-data.md +++ b/pages/vega-in-r/changing-data.md @@ -123,12 +123,12 @@ Below is the code to make this plot. ```R data_source_subset = subset(data_source, data_source$Entity != "All natural disasters") -chart_disasters = - alt$Chart(data_source_subset)$ +chart_disasters = alt$Chart(data_source_subset)$ mark_circle( opacity=0.8, stroke='black', - strokeWidth=1)$ + strokeWidth=1 + )$ encode( x = "Year:O", y = "Entity:N", @@ -145,15 +145,13 @@ Using the mark type `rect` with `color` and `opacity` channels we can make a hea ```R -chart_disasters_2 = - alt$Chart(data_source_subset)$ +chart_disasters = alt$Chart(data_source_subset)$ mark_rect()$ encode( x = "Entity:O", y = "Year:O", color = "Entity:N", - opacity = 'Deaths:Q', - tooltip = c("Year:O", "Deaths:Q") + opacity = 'Deaths:Q' )$ properties( height=600, @@ -282,8 +280,5 @@ chart_disasters = alt$Chart(data_source_subset)$ {:.exercise} **Exercise** - Change the field types. What is the result? -{:.exercise} -**Exercise** - Make a barchart for total Deaths per Entity. Hint: You may do the calculation in R or try a calculation inside encoding. - {% include custom/series_vega-in-r_next.html %} diff --git a/pages/vega-in-r/data-transformations.md b/pages/vega-in-r/data-transformations.md index b9adae4..e1fbd69 100644 --- a/pages/vega-in-r/data-transformations.md +++ b/pages/vega-in-r/data-transformations.md @@ -127,7 +127,7 @@ We now also use the `transform_window()` for data transformation to compute and ```R chart_disasters = alt$Chart("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")$ transform_window( - cumulative_count='sum(Deaths)' + cumulative_count='sum(Deaths)' )$ mark_area()$ encode( diff --git a/pages/vega-in-r/field-transform.md b/pages/vega-in-r/field-transform.md index e9a1f85..6e5946a 100644 --- a/pages/vega-in-r/field-transform.md +++ b/pages/vega-in-r/field-transform.md @@ -71,7 +71,7 @@ chart_disasters = alt$Chart(data_source_subset)$
-Mind the difference in the syntax here. We used the long form `x = alt$X()` so that we can specify the binning inside encoding. Other adjustments can be related to scale or axis. +Mind the difference in the syntax here. We used the long form `x = alt$X()`, we have seen in the simple barchart section, so that we can specify the binning inside encoding. Other adjustments can be related to scale or axis.
@@ -212,14 +212,15 @@ For instance, we can transform a quantitative field using the log scale, as we c ```R chart_disasters = alt$Chart("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")$ - mark_bar()$encode( + mark_bar()$ + encode( x = 'Entity:N', y = alt$Y('sum(Deaths):Q', scale=alt$Scale(type='log')) - )$properties( + )$ + properties( height = 300, width = 600 -) - + ) ```
@@ -279,20 +280,21 @@ Now we can plot the full time series, and specify a custom color scale for the p So, the domain of the data is `0` for Non-Missing, `1` for Missing and the custom range is the two colors of our preference, here black and red. ```R -domain_color = c("0", "1") +domain_var = c("0", "1") range_color = c('black', 'red') +range_size = c(50, 150) data_source_subset = subset(data_source_modified, data_source_modified$Entity == "All natural disasters") chart_disasters = alt$Chart(data_source_subset)$ mark_circle( - opacity = 0.8, - size = 50 + opacity = 0.8 )$ encode( x = 'Year:O', y = 'Deaths:Q', - color = alt$Color('Missing', scale = alt$Scale(domain = domain_color, range = range_color)), + color = alt$Color('Missing', scale = alt$Scale(domain = domain_var, range = range_color)), + size = alt$Size('Missing', scale = alt$Scale(domain = domain_var, range = range_size)), tooltip = c("Year", "Deaths") )$ properties( @@ -1043,6 +1045,20 @@ chart_disasters = alt$Chart(data_source_subset)$ }, "type": "nominal" }, + "size": { + "field": "Missing", + "scale": { + "domain": [ + "0", + "1" + ], + "range": [ + 50, + 150 + ] + }, + "type": "nominal" + }, "tooltip": [ { "field": "Year", @@ -1065,11 +1081,10 @@ chart_disasters = alt$Chart(data_source_subset)$ "height": 300, "mark": { "opacity": 0.8, - "size": 50, "type": "circle" }, "selection": { - "selector033": { + "selector005": { "bind": "scales", "encodings": [ "x", diff --git a/pages/vega-in-r/setting-things-up.md b/pages/vega-in-r/setting-things-up.md index 7f1a3cc..010d7e8 100644 --- a/pages/vega-in-r/setting-things-up.md +++ b/pages/vega-in-r/setting-things-up.md @@ -34,12 +34,12 @@ install.packages("reticulate") reticulate::use_condaenv("r-reticulate") ``` -Restart R studio and then install the altair package: +Restart Rstudio and then install the altair package: ``` R install.packages("altair") ``` -In R studio, use the code below to install the Python packages altair and vega_datasets: +In Rstudio, use the code below to install the Python packages altair and vega_datasets: ``` R altair::install_altair() ``` diff --git a/pages/vega-in-r/simple-barchart.md b/pages/vega-in-r/simple-barchart.md index d5467f4..53d6e59 100644 --- a/pages/vega-in-r/simple-barchart.md +++ b/pages/vega-in-r/simple-barchart.md @@ -81,13 +81,13 @@ and below is the code to generate it: ```R -chart_1 = - alt$Chart(dataset) - $mark_bar() - $encode( +chart_1 = alt$Chart(dataset)$ + mark_bar()$ + encode( x = "Var1:O", - y = "Var2:Q") - $properties( + y = "Var2:Q" + )$ + properties( height=200, width=400 ) @@ -96,8 +96,8 @@ chart_1 = What is the syntax in altair R? It is similar to the altair Python with the major difference the usage of the operator `$` to access attributes, instead of `.`. We should note that there are some other differences of the Python and the R package described at the [Field Guide to Python Issues](https://vegawidget.github.io/altair/articles/field-guide-python.html) together with examples. We should also notice that we use the object `alt` to access the Altair API and create a chart using `alt$Chart`. - The `data` to be visualised is called inside the `alt$Chart`. -- The `mark` used is specifed after `mark_`. -- The `encode` determines the mapping between the channels and the data. Here, `x` and `y` are the position channels. The field type is specified after the field name. `O` stands for ordinal and `Q` for quantitative. The `x = "Var1:O"` is the short form of `x = alt$X("Var1", type = "ordinal")`. The two forms are equivalent but the long form is used when doing more adjustments unside encoding. We will see an example in the field transform section. +- The `mark` used is specifed after `mark_`. Values as properties of the marks, for instance a hard-coded size or color, can be specified here. +- The `encode` determines the mapping between the channels and the data fields. The encoding that is dependent on the fields is specified here, not the encoding that has to do with values of the marks. Here, `x` and `y` are the position channels. The field type is specified after the field name. `O` stands for ordinal and `Q` for quantitative. Other types are `N` for nominal, `T` for temporal and `G` for goejson. The `x = "Var1:O"` is the short form of `x = alt$X("Var1", type = "ordinal")`. The two forms are equivalent but the long form is used when doing more adjustments unside encoding. We will see an example in the field transform section. - The height and width of the plot is specified inside `properties`. To display the chart in Rstudio `vegawidget(chart_1)` or `chart_1` will not work. We can instead save the chart using: @@ -111,62 +111,9 @@ To examine the chart specification in R we can install the package listviewer us vegawidget::vw_examine(chart_1, mode = "code") ``` The output is below: -```R -{ - "$schema": "https://vega.github.io/schema/vega-lite/v4.0.0.json", - "config": { - "view": { - "continuousHeight": 300, - "continuousWidth": 400 - } - }, - "data": { - "name": "data-c15a74353a288269433adfdc7c0ad142" - }, - "datasets": { - "data-c15a74353a288269433adfdc7c0ad142": [ - { - "Var1": "a", - "Var2": 11, - "Var3": "type1" - }, - { - "Var1": "b", - "Var2": 19, - "Var3": "type1" - }, - { - "Var1": "c", - "Var2": 22, - "Var3": "type2" - }, - { - "Var1": "d", - "Var2": 8, - "Var3": "type1" - }, - { - "Var1": "e", - "Var2": 14, - "Var3": "type2" - } - ] - }, - "encoding": { - "x": { - "field": "Var1", - "type": "ordinal" - }, - "y": { - "field": "Var2", - "type": "quantitative" - } - }, - "height": 200, - "mark": "bar", - "width": 400 -} -``` + +![screenshot_code]({{ site.baseurl }}/assets/screenshot_code.PNG) + {:.exercise} **Exercise** - Make yourself comfortable with the basic syntax of the chart in the altair R. Use the color channel for `Var3` to make the chart below. Change the height and width of the panel. diff --git a/pages/vega-in-r/simple-interaction.md b/pages/vega-in-r/simple-interaction.md index 289900f..9cc816e 100644 --- a/pages/vega-in-r/simple-interaction.md +++ b/pages/vega-in-r/simple-interaction.md @@ -28,7 +28,7 @@ tooltip = c("Variable_1:T", "Variable_2:T") ... ``` -Mind that if we are importing the data from a url directly in the plot specification, we may need to specify the field type. As shown above we may use ":T" for the type, where "T" may be `O` for orninal, `Q` for quantitative or `N` for nominal. Other types are `T` for temporal and `G` for goejson. +Mind that if we are importing the data from a url directly in the plot specification, we may need to specify the field type. As shown above we may use "T" for the type, where "T" may be for instance `O` for orninal, `Q` for quantitative or `N` for nominal.
From 5c7143453cf1b69e3c12f9e63d4c91a2dae05154 Mon Sep 17 00:00:00 2001 From: Danai Kafetzaki Date: Wed, 1 Apr 2020 21:51:43 +0200 Subject: [PATCH 15/17] Add files via upload --- assets/screenshot_code.PNG | Bin 0 -> 111803 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 assets/screenshot_code.PNG diff --git a/assets/screenshot_code.PNG b/assets/screenshot_code.PNG new file mode 100644 index 0000000000000000000000000000000000000000..02330c6e564ab54debd11a10fc1d64dca2fc6686 GIT binary patch literal 111803 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
  • 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

    7yM#YyVpcj^!_au=`8Twx(uo&ep{H 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 literal 0 HcmV?d00001 From 30779e1900703c70e70493ccef5d75564e38ab43 Mon Sep 17 00:00:00 2001 From: Danai Kafetzaki Date: Mon, 6 Apr 2020 15:13:00 +0200 Subject: [PATCH 16/17] corrected display and added references --- pages/vega-in-r/brush-and-link.md | 4 ++-- pages/vega-in-r/changing-data.md | 8 ++++---- pages/vega-in-r/data-transformations.md | 6 +++--- pages/vega-in-r/layered-chart.md | 2 +- pages/vega-in-r/setting-things-up.md | 7 +++++-- pages/vega-in-r/simple-barchart.md | 8 +++++--- pages/vega-in-r/simple-interaction.md | 4 ++-- 7 files changed, 22 insertions(+), 17 deletions(-) diff --git a/pages/vega-in-r/brush-and-link.md b/pages/vega-in-r/brush-and-link.md index ba2dda7..4404489 100644 --- a/pages/vega-in-r/brush-and-link.md +++ b/pages/vega-in-r/brush-and-link.md @@ -8,8 +8,8 @@ series: vega-in-r-series weight: 10 --- -We have seen how to concatenate charts, we may now see how to connect them interactively. -- To do so, we first create a static chart using the step 1 of the code below. +We have seen how to concatenate charts, we may now see how to connect them interactively. The steps described here are based on the [Interactive Examples article](https://vegawidget.github.io/altair/articles/interactive.html). +- To get started, we create a static chart using the step 1 of the code below. - The second step is to add a selection. Here we add a selection of type `interval` but a selection can also be `single` or `multi` [altair.selection reference](https://altair-viz.github.io/user_guide/generated/api/altair.selection.html?highlight=selection#altair.selection). In step 2, we also name the selection 'brush' and we update the static chart by including the selection function. - Finally, in step 3, we update the color encoding of the data, so that every time the chart is brused the data inside the selection are colored, based on the nominal variable `Missing`, and the rest are colored lightgray. diff --git a/pages/vega-in-r/changing-data.md b/pages/vega-in-r/changing-data.md index df4c141..18a21e3 100644 --- a/pages/vega-in-r/changing-data.md +++ b/pages/vega-in-r/changing-data.md @@ -9,12 +9,12 @@ weight: 3 --- Let's now use a more realistic example and visualize a dataset included in the `vega_datasets` package [https://github.com/vega/vega-datasets.html](https://github.com/vega/vega-datasets.html). -You can import the vega datasets using the altair library. +We can import the vega datasets using the altair library. ```R vega_data = altair::import_vega_data() ``` -See the list of the available datasets +Check out the list of the available datasets: ```R vega_data$list_datasets() ``` @@ -71,7 +71,7 @@ head(data_source); tail(data_source) ``` We can now make an altair R plot similar to the one at altair Python [https://altair-viz.github.io/gallery/natural_disasters.html](https://altair-viz.github.io/gallery/natural_disasters.html) -For now, we may filter the data in R and use the subset of the data to make the chart. On the data transform section we will see how to do the filtering inside the altair chart specification. +For now, we may filter the data in R and use the subset of the data to make the chart. On the data transform section we will see how to do the filtering inside the chart specification.
    @@ -140,7 +140,7 @@ chart_disasters = alt$Chart(data_source_subset)$ width=500 ) ``` -The global properties of the circles are specified inside the mark attribute and the properties that depend on the data inside the encoding. +Here, the global properties of the circles are specified inside the mark attribute while the properties that depend on the data inside the encoding. Using the mark type `rect` with `color` and `opacity` channels we can make a heatmap plot. diff --git a/pages/vega-in-r/data-transformations.md b/pages/vega-in-r/data-transformations.md index e1fbd69..4a13fe0 100644 --- a/pages/vega-in-r/data-transformations.md +++ b/pages/vega-in-r/data-transformations.md @@ -8,8 +8,8 @@ series: vega-in-r-series weight: 6 --- -As mentioned in the documentation of altair, [https://altair-viz.github.io/user_guide/transform/index.html](https://altair-viz.github.io/user_guide/transform/index.html) in most cases, it is suggested to perform transformations outside the chart definition, so in our case using R. Of course, data transforms inside the chart can also be useful in some cases. -So far, we have been filtering the data in R and then using the modified data in the chart specification. Now, we use the `transform_filter()` to subset the data inside the chart. We make the linechart we have seen in a previous section using the code below: +As mentioned in the [data transformations documentation](https://altair-viz.github.io/user_guide/transform/index.html) of altair, in most cases, it is suggested to perform transformations outside the chart definition, so in our case using R. Of course, data transforms inside the chart can also be useful in some cases. +So far, we have been filtering the data in R and then using the modified data in the chart specification. Now, we use the `transform_filter()` to subset the data inside the chart. [Here](https://altair-viz.github.io/user_guide/transform/filter.html#user-guide-filter-transform) is the filter transfrom documentation. We make the linechart we have seen in a previous section using the code below: ```R chart_disasters = alt$Chart("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")$ @@ -121,7 +121,7 @@ We use the field predicates to assess whether a data point satisfied certain con
    -We now also use the `transform_window()` for data transformation to compute and plot a windowed aggregation of the deaths over all available years. +We now also use the `transform_window()` for data transformation to compute and plot a windowed aggregation of the deaths over all available years. [Here](https://altair-viz.github.io/user_guide/transform/window.html#user-guide-window-transform) is the window transform documentation. ```R diff --git a/pages/vega-in-r/layered-chart.md b/pages/vega-in-r/layered-chart.md index d243c9a..6f8b153 100644 --- a/pages/vega-in-r/layered-chart.md +++ b/pages/vega-in-r/layered-chart.md @@ -8,7 +8,7 @@ series: vega-in-r-series weight: 7 --- -We are now looking at how we can combine charts in one canvas in altair R. +We are now looking at how we can combine charts in one canvas in altair R. This section on how to combine charts, is based on the [View Composition article](https://vegawidget.github.io/altair/articles/view-composition.html). First, we are discussing a layered chart example. Each chart can be made separately and combined uisng the `+` operator: `chart_layer_1 + chart_layer_2`. Below, we make a chart that consists of a line layer and a point layer. The tooltip should be added to the top layer so that it is visible in the final chart. diff --git a/pages/vega-in-r/setting-things-up.md b/pages/vega-in-r/setting-things-up.md index 010d7e8..41fcc35 100644 --- a/pages/vega-in-r/setting-things-up.md +++ b/pages/vega-in-r/setting-things-up.md @@ -9,9 +9,10 @@ weight: 1 --- To get this tutorial started, we need, first, to install anaconda, and second, activate an r-reticulate environment using conda. We also need to install vega_datasets using pip and finally, install the R packages reticulate and altair using install.packages() in Rstudio. -Most of the steps described here are taken from [altair R installation](https://vegawidget.github.io/altair/articles/installation.html). +Most of the steps described here are taken from [altair R installation](https://vegawidget.github.io/altair/articles/installation.html). Make sure you are using Python version 3.5 or higher to comply to the system requirements of the altair R package [altair CRAN](https://cran.r-project.org/web/packages/altair/altair.pdf). -After installing Anaconda, open the Anaconda Prompt. Update conda: +First, [install Anaconda](https://www.anaconda.com/distribution/) and after installing Anaconda, open the Anaconda Prompt. +Update conda: ``` C conda -V conda update conda @@ -49,6 +50,8 @@ Verify the installation using: altair::check_altair() ``` +If there is no error on the verification, we are ready to start! +
    The procedure described above should be run only in the beginning. The following times you want to use altair in Rstudio, you only need to call `library("altair")`. diff --git a/pages/vega-in-r/simple-barchart.md b/pages/vega-in-r/simple-barchart.md index 53d6e59..e6d8ba3 100644 --- a/pages/vega-in-r/simple-barchart.md +++ b/pages/vega-in-r/simple-barchart.md @@ -93,14 +93,16 @@ chart_1 = alt$Chart(dataset)$ ) ``` -What is the syntax in altair R? It is similar to the altair Python with the major difference the usage of the operator `$` to access attributes, instead of `.`. We should note that there are some other differences of the Python and the R package described at the [Field Guide to Python Issues](https://vegawidget.github.io/altair/articles/field-guide-python.html) together with examples. -We should also notice that we use the object `alt` to access the Altair API and create a chart using `alt$Chart`. +What is the syntax in altair R? It is similar to the altair Python with the major difference the usage of the operator `$` to access attributes, instead of `.`. We should note that there are some other differences of the Python and the R package described at the [Field Guide to Python Issues](https://vegawidget.github.io/altair/articles/field-guide-python.html) together with examples. Below, are the most common properties of the chart syntax: +- We first need to use the object `alt` to access the Altair API and create a chart using `alt$Chart`. - The `data` to be visualised is called inside the `alt$Chart`. - The `mark` used is specifed after `mark_`. Values as properties of the marks, for instance a hard-coded size or color, can be specified here. - The `encode` determines the mapping between the channels and the data fields. The encoding that is dependent on the fields is specified here, not the encoding that has to do with values of the marks. Here, `x` and `y` are the position channels. The field type is specified after the field name. `O` stands for ordinal and `Q` for quantitative. Other types are `N` for nominal, `T` for temporal and `G` for goejson. The `x = "Var1:O"` is the short form of `x = alt$X("Var1", type = "ordinal")`. The two forms are equivalent but the long form is used when doing more adjustments unside encoding. We will see an example in the field transform section. - The height and width of the plot is specified inside `properties`. -To display the chart in Rstudio `vegawidget(chart_1)` or `chart_1` will not work. We can instead save the chart using: +For more detailed references in Altair classes and functions, we may look to the [API reference](https://altair-viz.github.io/user_guide/API.html). + +Now, to display the chart in Rstudio we may use `vegawidget(chart_1)` or `chart_1`. Alternatively, we can also save the chart using: ```R htmlwidgets::saveWidget(vegawidget(chart_1),'chart_1.html') ``` diff --git a/pages/vega-in-r/simple-interaction.md b/pages/vega-in-r/simple-interaction.md index 9cc816e..ce49ff0 100644 --- a/pages/vega-in-r/simple-interaction.md +++ b/pages/vega-in-r/simple-interaction.md @@ -12,7 +12,7 @@ One of the main advantages to use the altair package is the fact that supports t ## Tooltip -A tooltip can be added to the plot using `tooltip()` inside `encode()`. For one variable displayed in the tooltip we can use: +A tooltip can be added to the plot using `tooltip()` inside `encode()` [altair R tooltips](https://vegawidget.github.io/altair/articles/tooltips.html). For one variable displayed in the tooltip we can use: ```R ... @@ -29,7 +29,7 @@ tooltip = c("Variable_1:T", "Variable_2:T") ``` Mind that if we are importing the data from a url directly in the plot specification, we may need to specify the field type. As shown above we may use "T" for the type, where "T" may be for instance `O` for orninal, `Q` for quantitative or `N` for nominal. - +We may also use the long form `alt$Tooltip(field = "Entity", type = "nominal")` and get the same result, or modify the tooltip specifying for instance a title, using `alt$Tooltip(field = "Entity", type = "nominal", title = "Disaster")`.

    + +
    + +Now that we have created our brushable chart, we may decrease the size of the first chart, so that we can easily display two charts in the screen. +If we now make a second chart that inherits all the properties of the first chart but we only change the x position encoding to `Entity`, we get the two-way brushable and linkable visalisation below. + +```R +chart_2a = chart_1$properties(width = 300, height = 300) +chart_2b = chart_2a$encode(x = "Entity:N") + +chart_disasters = (chart_2a | chart_2b) +``` + +
    + + +
    + +{:.exercise} +**Exercise** - Make a one-way brushable and linkable chart of the deaths versus time per entity. The interval selection appears in a barchart below. Hint: Check the [altair R gallery of interactive charts](https://vegawidget.github.io/altair/articles/example-gallery-08-interactive-charts.html) + + +
    + + + + +{% include custom/series_vega-in-r_next.html %} diff --git a/changing-data.md b/changing-data.md new file mode 100644 index 0000000..18a21e3 --- /dev/null +++ b/changing-data.md @@ -0,0 +1,284 @@ +--- +title: Changing data +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-changing-data.html +folder: vega-in-r +series: vega-in-r-series +weight: 3 +--- +Let's now use a more realistic example and visualize a dataset included in the `vega_datasets` package [https://github.com/vega/vega-datasets.html](https://github.com/vega/vega-datasets.html). + +We can import the vega datasets using the altair library. +```R +vega_data = altair::import_vega_data() +``` + +Check out the list of the available datasets: +```R +vega_data$list_datasets() +``` + +and select the one you want to work with. Here, we are using the dataset for [Natural Disasters from Our World in Data](https://ourworldindata.org/natural-disasters.html). +```R +data_source = vega_data$disasters() +``` + +Alternatively, you may load data from a local file using standard R code, or read the data from a url using: +```R +data_source = read.csv(url("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")) +``` + +After importing the data, we can take a first look using standard R code: + +```R +str(data_source) +summary(data_source) +head(data_source); tail(data_source) +``` + +```R +> str(data_source) +'data.frame': 803 obs. of 3 variables: + $ Entity: Factor w/ 11 levels "All natural disasters",..: 1 1 1 1 1 1 1 1 1 1 ... + $ Year : int 1900 1901 1902 1903 1905 1906 1907 1908 1909 1910 ... + $ Deaths: int 1267360 200018 46037 6506 22758 42970 1325641 75033 1511524 148233 ... +> summary(data_source) + Entity Year Deaths + All natural disasters:117 Min. :1900 Min. : 1 + Earthquake :111 1st Qu.:1946 1st Qu.: 270 + Extreme weather :111 Median :1975 Median : 1893 + Flood : 89 Mean :1969 Mean : 81213 + Landslide : 79 3rd Qu.:1996 3rd Qu.: 10362 + Epidemic : 69 Max. :2017 Max. :3706227 + (Other) :227 +> head(data_source) + Entity Year Deaths +1 All natural disasters 1900 1267360 +2 All natural disasters 1901 200018 +3 All natural disasters 1902 46037 +4 All natural disasters 1903 6506 +5 All natural disasters 1905 22758 +6 All natural disasters 1906 42970 +> tail(data_source) + Entity Year Deaths +798 Wildfire 2012 21 +799 Wildfire 2013 35 +800 Wildfire 2014 16 +801 Wildfire 2015 67 +802 Wildfire 2016 39 +803 Wildfire 2017 75 +``` + +We can now make an altair R plot similar to the one at altair Python [https://altair-viz.github.io/gallery/natural_disasters.html](https://altair-viz.github.io/gallery/natural_disasters.html) +For now, we may filter the data in R and use the subset of the data to make the chart. On the data transform section we will see how to do the filtering inside the chart specification. + +
    + +
    + + + +Below is the code to make this plot. +```R +data_source_subset = subset(data_source, data_source$Entity != "All natural disasters") + +chart_disasters = alt$Chart(data_source_subset)$ + mark_circle( + opacity=0.8, + stroke='black', + strokeWidth=1 + )$ + encode( + x = "Year:O", + y = "Entity:N", + color = "Entity:N", + size = "Deaths:Q" + )$ + properties( + height=200, + width=500 + ) +``` +Here, the global properties of the circles are specified inside the mark attribute while the properties that depend on the data inside the encoding. +Using the mark type `rect` with `color` and `opacity` channels we can make a heatmap plot. + + +```R +chart_disasters = alt$Chart(data_source_subset)$ + mark_rect()$ + encode( + x = "Entity:O", + y = "Year:O", + color = "Entity:N", + opacity = 'Deaths:Q' + )$ + properties( + height=600, + width=200 + ) +``` + + +
    + + +Next, using the code below, we can make a time series plot of deaths from all natural disasters from 1900 until 2017. + +```R +data_source_subset = subset(data_source, data_source$Entity == "All natural disasters") + +chart_disasters = alt$Chart(data_source_subset)$ + mark_line()$ + encode( + x='Year:Q', + y='Deaths:Q', + tooltip = c("Year", "Deaths") + )$ + properties( + height=300, + width=600 + ) +``` + +
    + + + +{:.exercise} +**Exercise** - Use the `color` channel to make a time series plot per Entity. + +{:.exercise} +**Exercise** - Change the field types. What is the result? + + +{% include custom/series_vega-in-r_next.html %} diff --git a/data-transformations.md b/data-transformations.md new file mode 100644 index 0000000..4a13fe0 --- /dev/null +++ b/data-transformations.md @@ -0,0 +1,205 @@ +--- +title: Data Transform +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-data-transformations.html +folder: vega-in-r +series: vega-in-r-series +weight: 6 +--- + +As mentioned in the [data transformations documentation](https://altair-viz.github.io/user_guide/transform/index.html) of altair, in most cases, it is suggested to perform transformations outside the chart definition, so in our case using R. Of course, data transforms inside the chart can also be useful in some cases. +So far, we have been filtering the data in R and then using the modified data in the chart specification. Now, we use the `transform_filter()` to subset the data inside the chart. [Here](https://altair-viz.github.io/user_guide/transform/filter.html#user-guide-filter-transform) is the filter transfrom documentation. We make the linechart we have seen in a previous section using the code below: + +```R +chart_disasters = alt$Chart("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")$ + mark_line()$ + encode( + x = 'Year:Q', + y = 'Deaths:Q', + tooltip = c("Year", "Deaths") + )$ + properties( + height = 300, + width = 600 + )$ + transform_filter( + alt$FieldEqualPredicate(field = "Entity", equal = "All natural disasters") + ) +``` + +
    + + +
    + +We use the field predicates to assess whether a data point satisfied certain conditions. As mentioned in the [field predicates reference](https://altair-viz.github.io/user_guide/transform/filter.html#field-predicates) the `FieldEqualPredicate` evaluates whether a field is equal to a particular value. The variable is the first argument and the condition is the second argument. Go through the field predicates altair documentation and [vega-lite documentation](https://vega.github.io/vega-lite/docs/predicate.html#field-predicate) and use the `FieldOneOfPredicate` for the exercise below. + + +{:.exercise} +**Exercise** - Use the filter transform to obtain the data related to volcanic activity and earthquake and make an area chart like the one below. + +
    + + +
    + +We now also use the `transform_window()` for data transformation to compute and plot a windowed aggregation of the deaths over all available years. [Here](https://altair-viz.github.io/user_guide/transform/window.html#user-guide-window-transform) is the window transform documentation. + + +```R +chart_disasters = alt$Chart("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")$ + transform_window( + cumulative_count='sum(Deaths)' + )$ + mark_area()$ + encode( + x = 'Year:O', + y = 'cumulative_count:Q', + tooltip = c("Year:Q", 'cumulative_count:Q') + )$transform_filter( + alt$FieldEqualPredicate(field = "Entity", equal = "All natural disasters") + )$ + properties( + height = 300, + width = 600 + ) +``` + +
    + + + + +{% include custom/series_vega-in-r_next.html %} diff --git a/layered-chart.md b/layered-chart.md new file mode 100644 index 0000000..6f8b153 --- /dev/null +++ b/layered-chart.md @@ -0,0 +1,8000 @@ +--- +title: Layered chart +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-layered-chart.html +folder: vega-in-r +series: vega-in-r-series +weight: 7 +--- + +We are now looking at how we can combine charts in one canvas in altair R. This section on how to combine charts, is based on the [View Composition article](https://vegawidget.github.io/altair/articles/view-composition.html). + +First, we are discussing a layered chart example. Each chart can be made separately and combined uisng the `+` operator: `chart_layer_1 + chart_layer_2`. +Below, we make a chart that consists of a line layer and a point layer. The tooltip should be added to the top layer so that it is visible in the final chart. + +```R +chart_disasters_L1 = alt$Chart("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")$ + mark_line()$ + encode( + x = 'Year:O', + y = 'Deaths:Q' + )$ + transform_filter( + alt$FieldEqualPredicate(field = "Entity", equal = "All natural disasters") + )$ + properties( + height = 400, + width = 600 + ) + +chart_disasters_L2 = alt$Chart("https://raw.githubusercontent.com/vega/vega-datasets/master/data/disasters.csv")$ + mark_point()$ + encode( + x = 'Year:O', + y = 'Deaths:Q', + tooltip = "Deaths:Q" + )$ + transform_filter( + alt$FieldEqualPredicate(field = "Entity", equal = "All natural disasters") + )$ + properties( + height = 400, + width = 600 + ) + +chart_disasters = (chart_disasters_L1 + chart_disasters_L2) +``` + + +
    + + +
    + +To produce the same chart we may also follow the procedure below. +Use the R code provided above for `chart_disasters_L2` and then make the first layer using: + +```R +chart_disasters_L1 = chart_disasters_L2$mark_line() +``` + +Then superimpose the charts as before: +```R +chart_disasters = (chart_disasters_L1 + chart_disasters_L2) +``` + +{:.exercise} +**Exercise** - Make a layered chart, which consists of one layer for the bar mark and one for the text mark, to produce the chart below. + + + +
    + + + +{% include custom/series_vega-in-r_next.html %} diff --git a/setting-things-up.md b/setting-things-up.md new file mode 100644 index 0000000..41fcc35 --- /dev/null +++ b/setting-things-up.md @@ -0,0 +1,60 @@ +--- +title: Setting things up +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-setting-things-up.html +folder: vega-in-r +series: vega-in-r-series +weight: 1 +--- + +To get this tutorial started, we need, first, to install anaconda, and second, activate an r-reticulate environment using conda. We also need to install vega_datasets using pip and finally, install the R packages reticulate and altair using install.packages() in Rstudio. +Most of the steps described here are taken from [altair R installation](https://vegawidget.github.io/altair/articles/installation.html). Make sure you are using Python version 3.5 or higher to comply to the system requirements of the altair R package [altair CRAN](https://cran.r-project.org/web/packages/altair/altair.pdf). + +First, [install Anaconda](https://www.anaconda.com/distribution/) and after installing Anaconda, open the Anaconda Prompt. +Update conda: +``` C +conda -V +conda update conda +```` + +Install the vega datasets that we will be used in this tutorial: +``` C +pip install vega_datasets +``` + +Next, create and activate a conda environmnet called `r-reticulate`: +``` C +conda create -n r-reticulate +conda activate r-reticulate +``` + +Open Rstudio IDE and install reticulate. Then, use the conda environment `r-reticulate`: +``` R +install.packages("reticulate") +reticulate::use_condaenv("r-reticulate") +``` + +Restart Rstudio and then install the altair package: +``` R +install.packages("altair") +``` + +In Rstudio, use the code below to install the Python packages altair and vega_datasets: +``` R +altair::install_altair() +``` + +Verify the installation using: +``` R +altair::check_altair() +``` + +If there is no error on the verification, we are ready to start! +
    +The procedure described above should be run only in the beginning. The following times you want to use altair in Rstudio, you only need to call `library("altair")`. + + + + +{% include custom/series_vega-in-r_next.html %} diff --git a/simple-barchart.md b/simple-barchart.md new file mode 100644 index 0000000..66c9167 --- /dev/null +++ b/simple-barchart.md @@ -0,0 +1,193 @@ +--- +title: A simple barchart +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-simple-barchart.html +folder: vega-in-r +series: vega-in-r-series +weight: 2 +--- +Here is a very simple barchart defined in altair R. + +
    + + +The dataset used for this chart is: + +```R +Var1 = c("a","b","c","d","e") +Var2 = c(11, 19, 22, 8, 14) +Var3 = c("type1","type1","type2","type1","type2") +dataset = data.frame(Var1, Var2, Var3) +``` + +and below is the code to generate it: + + +```R +chart_1 = alt$Chart(dataset)$ + mark_bar()$ + encode( + x = "Var1:O", + y = "Var2:Q" + )$ + properties( + height=200, + width=400 + ) +``` + +What is the syntax in altair R? It is similar to the altair Python with the major difference the usage of the operator `$` to access attributes, instead of `.`. We should note that there are some other differences of the Python and the R package described at the [Field Guide to Python Issues](https://vegawidget.github.io/altair/articles/field-guide-python.html) together with examples. Below, are the most common properties of the chart syntax: +- We first need to use the object `alt` to access the Altair API and create a chart using `alt$Chart`. +- The `data` to be visualised is called inside the `alt$Chart`. +- The `mark` used is specifed after `mark_`. Values as properties of the marks, for instance a hard-coded size or color, can be specified here. +- The `encode` determines the mapping between the channels and the data fields. The encoding that is dependent on the fields is specified here, not the encoding that has to do with values of the marks. Here, `x` and `y` are the position channels. The field type is specified after the field name. `O` stands for ordinal and `Q` for quantitative. Other types are `N` for nominal, `T` for temporal and `G` for goejson. The `x = "Var1:O"` is the short form of `x = alt$X("Var1", type = "ordinal")`. The two forms are equivalent but the long form is used when doing more adjustments unside encoding. We will see an example in the field transform section. +- The height and width of the plot is specified inside `properties`. + +For more detailed references in Altair classes and functions, we may look to the [API reference](https://altair-viz.github.io/user_guide/API.html). + +Now, to display the chart in Rstudio we may use `vegawidget(chart_1)` or `chart_1`. Alternatively, we can also save the chart using: +```R +htmlwidgets::saveWidget(vegawidget(chart_1),'chart_1.html') +``` +and display it in the browser by opening the `chart_1.html` file. + +To examine the chart specification in R we can install the package listviewer using `install.packages("listviewer")` and use: +```R +vegawidget::vw_examine(chart_1, mode = "code") +``` +The output is below: + +![screenshot_code]({{ site.baseurl }}/assets/screenshot_code.png) + + +{:.exercise} +**Exercise** - Make yourself comfortable with the basic syntax of the chart in the altair R. Use the color channel for `Var3` to make the chart below. Change the height and width of the panel. + + +
    + + + +{:.exercise} +**Exercise** - Visualise the same data, using a point as the mark, change the color for all points to black and visualise Var3 using size. Format the axes. + + + +{% include custom/series_vega-in-r_next.html %} diff --git a/simple-interaction.md b/simple-interaction.md new file mode 100644 index 0000000..ce49ff0 --- /dev/null +++ b/simple-interaction.md @@ -0,0 +1,191 @@ +--- +title: Simple Interaction +keywords: vega-in-r +sidebar: vega-in-r_sidebar +permalink: /vega-in-r-simple-interaction.html +folder: vega-in-r +series: vega-in-r-series +weight: 4 +--- + +One of the main advantages to use the altair package is the fact that supports the generation of interactive graphics. The code required for adding a simple interaction is relatively short. + +## Tooltip + +A tooltip can be added to the plot using `tooltip()` inside `encode()` [altair R tooltips](https://vegawidget.github.io/altair/articles/tooltips.html). For one variable displayed in the tooltip we can use: + +```R +... +tooltip = "Variable_1:T" +... +``` + +and for more than one variable, we can use the R function `list()` or `c()` as illustrated below: + +```R +... +tooltip = c("Variable_1:T", "Variable_2:T") +... +``` + +Mind that if we are importing the data from a url directly in the plot specification, we may need to specify the field type. As shown above we may use "T" for the type, where "T" may be for instance `O` for orninal, `Q` for quantitative or `N` for nominal. +We may also use the long form `alt$Tooltip(field = "Entity", type = "nominal")` and get the same result, or modify the tooltip specifying for instance a title, using `alt$Tooltip(field = "Entity", type = "nominal", title = "Disaster")`. + +
    + + +{:.exercise} +**Exercise** - Add a tooltip in the heatmap we created in the previous section, to get the graph illustrated above. + + +## Zooming and Panning + +We illustrate two ways of making a graph zoomable and pannable. The first one is by adding the `intreactive()` attribute, as illustrated below: + +```R +chart = alt$Chart(data_source_subset)$ + ..... + $interactive() +``` + +A second option is to specify the selection outside the plot code and then use it inside the `add_selection` attribute in the chart code. +The second option is an interval selection using a scale binding. For more information on selection types supported in altair you can refer to [altair.selection_interval reference](https://altair-viz.github.io/user_guide/generated/api/altair.selection_interval.html#altair.selection_interval) + +```R +selection = alt$selection_interval(bind='scales') + +chart = alt$Chart(data_source_subset)$ +..... +$add_selection( + selection + ) +``` + +
    + + + +{:.exercise} +**Exercise** - Make the time series plot of all natural distasters interactive, to get the graph illustrated above. Use both ways of making it zoomable and pannable. + + +{% include custom/series_vega-in-r_next.html %}