knitr::opts_chunk$set( collapse = TRUE, comment = "##", fig.width = 8, fig.height = 5.5, out.width = "90%" ) library(tidyverse) library(viridisLite) theme_set(theme_minimal() + theme(legend.position = "bottom")) options( ggplot2.continuous.colour = "viridis", ggplot2.continuous.fill = "viridis" ) scale_colour_discrete <- scale_colour_viridis_d scale_fill_discrete <- scale_fill_viridis_d library("tidyfun") data(chf_df, package = "tidyfun") data(dti_df, package = "tidyfun") pal_5 <- viridis(7)[-(1:2)] set.seed(1221)
The tidyfun
package is designed to facilitate functional data analysis in R
, with particular emphasis on compatibility with the tidyverse
. In this vignette, we illustrate data visualization using tidyfun
.
We'll draw on tidyfun::chf_df
and tidyfun::dti_df
, as well as the fda::CanadianWeather
data.
ggplot
ggplot
is a powerful framework for visualization. In this section, we'll assume some basic familiarity with the package; if you're new to ggplot
, this primer may be helpful.
tidyfun
includes pasta-themed geom
s and plots for functional data:
geom_spaghetti
for linesgeom_meatballs
for (lines &) pointsgglasagna
for heatmaps, with an order
-argument for arranging lasagna layers / heat map rows.geom_capellini
for little sparklines / glyphs on maps etc.geom_errorband
-- a functional data version of geom_ribbon
geom_spaghetti
and geom_meatballs
One of the most fundamental plots for functional data is the spaghetti plot, which is implemented in tidyfun
+ ggplot
through geom_spaghetti
:
chf_df |> filter(id == 1) |> ggplot(aes(y = activity)) + geom_spaghetti()
A variant on the spaghetti plot is the meatballs plot, which shows both the "noodles" (i.e. functional observations visualized as curves) and the "meatballs" (i.e. observed data values visualized as points).
chf_df |> filter(id == 1, day == "Mon") |> ggplot(aes(y = activity)) + geom_meatballs()
ggplot
featuresThe new geoms in tidyfun
"play nicely" with standard ggplot
aesthetics and options.
You can, for example, define the color aesthetic for plots of tf
variables using other observations:
chf_df |> filter(id %in% 1:5) |> ggplot(aes(y = activity, color = gender)) + geom_spaghetti(alpha = 0.2)
You can also use facetting:
chf_df |> filter(day %in% c("Mon", "Sun")) |> ggplot(aes(y = activity, color = gender)) + geom_spaghetti(alpha = 0.1) + facet_grid(~day)
Another example, using the DTI data, is below.
dti_df |> ggplot() + geom_spaghetti(aes(y = cca, col = case, alpha = 0.2 + 0.4 * (case == "control"))) + facet_wrap(~sex) + scale_alpha(guide = "none", range = c(0.2, 0.4))
Together with tidyfun
's tools for functional data wrangling and summary statistics, the integration with ggplot2
can produce useful exploratory analyses,
like the plot below showing group-wise smoothed and unsmoothed mean activity profiles:
chf_df |> group_by(gender, day) |> summarize(mean_act = mean(activity)) |> mutate(smooth_mean = tfb(mean_act, verbose = FALSE)) |> filter(day %in% c("Mon", "Sun")) |> ggplot(aes(y = smooth_mean, color = gender)) + geom_spaghetti(linewidth = 1.25, alpha = 1) + geom_meatballs(aes(y = mean_act), alpha = 0.1) + facet_grid(~day)
... or the plot below showing group-wise mean functions +/- twice their pointwise standard errors:
chf_df |> group_by(gender, day) |> summarize( mean_act = mean(activity), sd_act = sd(activity) ) |> group_by(gender, day) |> mutate( upper_act = mean_act + 2 * sd_act, lower_act = mean_act - 2 * sd_act ) |> filter(day %in% c("Mon", "Sun")) |> ggplot(aes(y = mean_act, color = gender, fill = gender)) + geom_spaghetti(alpha = 1) + geom_errorband(aes(ymax = upper_act, ymin = lower_act), alpha = 0.3) + facet_grid(day ~ gender)
gglasagna
Lasagna plots are "a saucy alternative to spaghetti plots". They are a variant on a heatmaps which show functional observations in rows and use color to illustrate values taken at different arguments.
In tidyfun
, lasagna plots are implemented through gglasagna
. A first example, using the CHF data, is below.
chf_df |> filter(day %in% c("Mon", "Sun")) |> gglasagna(activity)
A somewhat more involved example, demonstrating the order
argument and taking advantage of facets, is next.
dti_df |> gglasagna( tf = cca, order = tf_integrate(cca, definite = TRUE), arg = seq(0, 1, length.out = 101) ) + theme(axis.text.y = element_text(size = 6)) + facet_wrap(~case, ncol = 2, scales = "free")
geom_capellini
To illustrate geom_capellini
, we'll start with some data prep for the iconic Canadian Weather data:
canada <- data.frame( place = fda::CanadianWeather$place, region = fda::CanadianWeather$region, lat = fda::CanadianWeather$coordinates[, 1], lon = -fda::CanadianWeather$coordinates[, 2] ) canada$temp <- tfd(t(fda::CanadianWeather$dailyAv[, , 1]), arg = 1:365) canada$precipl10 <- tfd(t(fda::CanadianWeather$dailyAv[, , 3]), arg = 1:365) |> tf_smooth() canada_map <- data.frame(maps::map("world", "Canada", plot = FALSE)[c("x", "y")])
Now we can plot a map of Canada with annual temperature averages in red, precipitation in blue:
ggplot(canada, aes(x = lon, y = lat)) + geom_capellini(aes(tf = precipl10), width = 4, height = 5, colour = "blue", line.linetype = 1 ) + geom_capellini(aes(tf = temp), width = 4, height = 5, colour = "red", line.linetype = 1 ) + geom_path(data = canada_map, aes(x = x, y = y), alpha = 0.1) + coord_quickmap()
tidyfun
includes several extensions of base R graphics, which operate on tf
vectors. For example, one can use plot
to create either spaghetti or lasagna plots, and lines
to add lines to an existing plot:
cca <- dti_df$cca |> tfd(arg = seq(0, 1, length.out = 93), interpolate = TRUE) layout(t(1:2)) plot(cca, type = "spaghetti") lines(c(median(cca), mean = mean(cca)), col = c(2, 4)) plot(cca, type = "lasagna", col = viridis(50))
These plot
methods use all the same graphics options and can be edited like other base graphics:
cca_five <- cca[1:5] cca_five |> plot(xlim = c(-0.15, 1), col = pal_5, lwd = 2) text( x = -0.1, y = cca_five[, 0.07], labels = names(cca_five), col = pal_5, cex = 1.5 ) median(cca_five) |> lines(col = pal_5[3], lwd = 4)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.