Search code examples
rgraphicsggplot2density-plot

2dDensity facet scale


I am making 2d Density graphs with some tracking data.

My goal is to make plots for each experimental unit

My df looks like this:

head(df)
  Caja  x  y          t
1    4  0  0 0:00:00:00
2    4 -2 10 0:00:00:14
3    4  3 26 0:00:00:28
4    4  7 54 0:00:00:42
5    4  9 75 0:00:00:57
6    4  9 92 0:00:00:71

The first column (Caja) is the factor I use for faceting (because each level is a different experimental unit). x and y are the variables I am interested in, t is just the time in which the measure was taken.

Since df is a long data.frane and I am going to use caja4 later I provide it

dput(caja4)
structure(list(Caja = c(4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L), x = c(0L, -2L, 
3L, 7L, 9L, 9L, 11L, 6L, -12L, -23L, -33L, -32L, -36L, -28L, 
-15L, -2L, 2L, 6L, 6L, 4L, 4L, 2L, 1L, 0L, -1L, 2L, 2L, 4L, 6L, 
11L, 9L, 11L, 13L, 12L, 0L, 3L, 10L, 5L, -14L, -10L, 5L, 10L, 
12L, 12L, 11L, 11L, 9L, 9L, 11L, 9L, 10L, 11L, 12L, 7L, 1L, -6L, 
-11L, -18L, -25L, -17L, -7L, -2L, -5L, -4L, -24L, -29L, -37L, 
-39L, -41L, -41L, -41L, -41L, -41L, -41L, -41L, -39L, -39L, -39L, 
-39L, -39L, -39L, -39L, -39L, -39L, -28L, -17L, -11L, -6L, -9L, 
-16L, -27L, -37L, -38L, -42L, -42L, -42L, -42L, -42L, -42L, -42L, 
-42L, -42L, -42L, -36L, -28L, -17L, -6L, 1L, 3L, 3L, 2L, 2L, 
2L, 2L, -2L, 1L, 0L, 0L, 2L, 4L, 5L, 4L, 2L, 3L, -1L, -1L, -9L, 
-12L, -30L, -38L, -37L, -36L, -42L, -42L, -42L, -42L, -42L, -43L, 
-43L, -43L, -36L, -35L, -29L, -26L, -29L, -37L, -38L, -38L, -38L, 
-37L, -31L, -18L, 5L, 7L, 7L, 8L, 7L, 4L, 7L, 2L, 5L, 10L, 13L, 
12L, -13L, -32L, -41L, -31L, -14L, 0L, 10L, 2L, -8L, -29L, -37L, 
-37L, -37L, -37L, -37L, -37L, -37L, -28L, -14L, -3L, 4L, 3L, 
1L, -7L, -15L, -11L, -11L, -15L, -16L, -27L, -37L, -43L, -43L, 
-43L, -43L, -43L, -43L, -43L, -24L, -1L, 0L, 3L, 4L, 3L, 2L, 
1L, 3L, 4L, -9L, -31L, -45L, -45L, -34L, -32L, -4L, -12L, -8L, 
-6L, -17L, -31L, -36L, -42L, -37L, -39L, -36L, -36L, -36L, -37L, 
-37L, -36L, -37L, -32L, -19L, -5L, 2L, 7L, 9L, 9L, 7L, 10L, 9L, 
10L, 11L, 11L, 11L, 8L, 8L, 10L, 12L, -1L, -14L, -32L, -17L, 
-2L, -14L, -26L, -44L, -44L, -44L, -44L, -44L, -44L, -45L, -45L, 
-33L, -21L, -12L, -11L, -5L, 2L, 5L, 4L, 2L, 6L, 6L, 6L, 6L, 
6L, 6L, 7L, -7L, -29L, -27L, -10L, -2L, 5L, 7L, 7L, 8L, 13L), 
    y = c(0L, 10L, 26L, 54L, 75L, 92L, 113L, 116L, 117L, 114L, 
    119L, 115L, 114L, 108L, 99L, 90L, 76L, 57L, 37L, 21L, 12L, 
    7L, 8L, 2L, -2L, 5L, 7L, 17L, 37L, 52L, 67L, 86L, 100L, 118L, 
    122L, 125L, 122L, 122L, 129L, 129L, 126L, 124L, 125L, 123L, 
    106L, 92L, 70L, 49L, 27L, 17L, 5L, 6L, 10L, 7L, 3L, -3L, 
    -3L, -6L, -8L, -13L, -13L, -14L, -13L, -13L, -5L, 1L, 3L, 
    7L, 8L, 9L, 10L, 25L, 42L, 44L, 57L, 87L, 101L, 107L, 110L, 
    102L, 96L, 94L, 81L, 68L, 57L, 50L, 61L, 76L, 96L, 97L, 96L, 
    98L, 99L, 95L, 79L, 64L, 53L, 46L, 31L, 12L, 4L, -7L, -16L, 
    -17L, -17L, -17L, -17L, -17L, -17L, -16L, -17L, -17L, -17L, 
    -17L, -17L, -17L, -17L, -17L, -6L, 15L, 31L, 50L, 71L, 95L, 
    105L, 119L, 125L, 119L, 117L, 116L, 127L, 112L, 94L, 77L, 
    55L, 26L, 0L, -1L, -2L, 1L, -4L, -5L, -5L, -6L, -10L, -11L, 
    -11L, -11L, -10L, -9L, -10L, -8L, 4L, 9L, 15L, 25L, 41L, 
    57L, 71L, 84L, 100L, 117L, 133L, 134L, 137L, 134L, 134L, 
    135L, 139L, 135L, 131L, 120L, 125L, 132L, 131L, 127L, 140L, 
    143L, 144L, 143L, 143L, 142L, 139L, 138L, 131L, 124L, 104L, 
    80L, 61L, 45L, 23L, 9L, -4L, -4L, -8L, -13L, -13L, -13L, 
    -13L, -13L, -13L, -13L, -10L, -2L, 0L, 7L, 24L, 36L, 56L, 
    77L, 108L, 123L, 137L, 139L, 129L, 130L, 117L, 128L, 123L, 
    117L, 126L, 125L, 124L, 145L, 145L, 107L, 104L, 92L, 83L, 
    75L, 62L, 47L, 32L, 17L, 1L, -7L, -8L, -10L, -8L, -5L, -6L, 
    -3L, -1L, 10L, 20L, 28L, 32L, 33L, 34L, 52L, 74L, 98L, 114L, 
    116L, 116L, 121L, 122L, 123L, 120L, 117L, 114L, 107L, 109L, 
    87L, 69L, 37L, 12L, 8L, -14L, -14L, -14L, -11L, 2L, 17L, 
    29L, 25L, 12L, -9L, 0L, 12L, 28L, 54L, 84L, 96L, 105L, 114L, 
    114L, 111L, 112L, 111L, 116L, 120L, 120L, 127L), t = structure(1:294, .Label = c("0:00:00:00", 
    "0:00:00:14", "0:00:00:28", "0:00:00:42", "0:00:00:57", "0:00:00:71", 
    "0:00:00:85", "0:00:01:00", "0:00:01:14", "0:00:01:28", "0:00:01:42", 
    "0:00:01:57", "0:00:01:71", "0:00:01:85", "0:00:02:00", "0:00:02:14", 
    "0:00:02:28", "0:00:02:42", "0:00:02:57", "0:00:02:71", "0:00:02:85", 
    "0:00:03:00", "0:00:03:14", "0:00:03:28", "0:00:03:42", "0:00:03:57", 
    "0:00:03:71", "0:00:03:85", "0:00:04:00", "0:00:04:14", "0:00:04:28", 
    "0:00:04:42", "0:00:04:57", "0:00:04:71", "0:00:04:85", "0:00:05:00", 
    "0:00:05:14", "0:00:05:28", "0:00:05:42", "0:00:05:57", "0:00:05:71", 
    "0:00:05:85", "0:00:06:00", "0:00:06:14", "0:00:06:28", "0:00:06:42", 
    "0:00:06:57", "0:00:06:71", "0:00:06:85", "0:00:07:00", "0:00:07:14", 
    "0:00:07:28", "0:00:07:42", "0:00:07:57", "0:00:07:71", "0:00:07:85", 
    "0:00:08:00", "0:00:08:14", "0:00:08:28", "0:00:08:42", "0:00:08:57", 
    "0:00:08:71", "0:00:08:85", "0:00:09:00", "0:00:09:14", "0:00:09:28", 
    "0:00:09:42", "0:00:09:57", "0:00:09:71", "0:00:09:85", "0:00:10:00", 
    "0:00:10:14", "0:00:10:28", "0:00:10:42", "0:00:10:57", "0:00:10:71", 
    "0:00:10:85", "0:00:11:00", "0:00:11:14", "0:00:11:28", "0:00:11:42", 
    "0:00:11:57", "0:00:11:71", "0:00:11:85", "0:00:12:00", "0:00:12:14", 
    "0:00:12:28", "0:00:12:42", "0:00:12:57", "0:00:12:71", "0:00:12:85", 
    "0:00:13:00", "0:00:13:14", "0:00:13:28", "0:00:13:42", "0:00:13:57", 
    "0:00:13:71", "0:00:13:85", "0:00:14:00", "0:00:14:14", "0:00:14:28", 
    "0:00:14:42", "0:00:14:57", "0:00:14:71", "0:00:14:85", "0:00:15:00", 
    "0:00:15:14", "0:00:15:28", "0:00:15:42", "0:00:15:57", "0:00:15:71", 
    "0:00:15:85", "0:00:16:00", "0:00:16:14", "0:00:16:28", "0:00:16:42", 
    "0:00:16:57", "0:00:16:71", "0:00:16:85", "0:00:17:00", "0:00:17:14", 
    "0:00:17:28", "0:00:17:42", "0:00:17:57", "0:00:17:71", "0:00:17:85", 
    "0:00:18:00", "0:00:18:14", "0:00:18:28", "0:00:18:42", "0:00:18:57", 
    "0:00:18:71", "0:00:18:85", "0:00:19:00", "0:00:19:14", "0:00:19:28", 
    "0:00:19:42", "0:00:19:57", "0:00:19:71", "0:00:19:85", "0:00:20:00", 
    "0:00:20:14", "0:00:20:28", "0:00:20:42", "0:00:20:57", "0:00:20:71", 
    "0:00:20:85", "0:00:21:00", "0:00:21:14", "0:00:21:28", "0:00:21:42", 
    "0:00:21:57", "0:00:21:71", "0:00:21:85", "0:00:22:00", "0:00:22:14", 
    "0:00:22:28", "0:00:22:42", "0:00:22:57", "0:00:22:71", "0:00:22:85", 
    "0:00:23:00", "0:00:23:14", "0:00:23:28", "0:00:23:42", "0:00:23:57", 
    "0:00:23:71", "0:00:23:85", "0:00:24:00", "0:00:24:14", "0:00:24:28", 
    "0:00:24:42", "0:00:24:57", "0:00:24:71", "0:00:24:85", "0:00:25:00", 
    "0:00:25:14", "0:00:25:28", "0:00:25:42", "0:00:25:57", "0:00:25:71", 
    "0:00:25:85", "0:00:26:00", "0:00:26:14", "0:00:26:28", "0:00:26:42", 
    "0:00:26:57", "0:00:26:71", "0:00:26:85", "0:00:27:00", "0:00:27:14", 
    "0:00:27:28", "0:00:27:42", "0:00:27:57", "0:00:27:71", "0:00:27:85", 
    "0:00:28:00", "0:00:28:14", "0:00:28:28", "0:00:28:42", "0:00:28:57", 
    "0:00:28:71", "0:00:28:85", "0:00:29:00", "0:00:29:14", "0:00:29:28", 
    "0:00:29:42", "0:00:29:57", "0:00:29:71", "0:00:29:85", "0:00:30:00", 
    "0:00:30:14", "0:00:30:28", "0:00:30:42", "0:00:30:57", "0:00:30:71", 
    "0:00:30:85", "0:00:31:00", "0:00:31:14", "0:00:31:28", "0:00:31:42", 
    "0:00:31:57", "0:00:31:71", "0:00:31:85", "0:00:32:00", "0:00:32:14", 
    "0:00:32:28", "0:00:32:42", "0:00:32:57", "0:00:32:71", "0:00:32:85", 
    "0:00:33:00", "0:00:33:14", "0:00:33:28", "0:00:33:42", "0:00:33:57", 
    "0:00:33:71", "0:00:33:85", "0:00:34:00", "0:00:34:14", "0:00:34:28", 
    "0:00:34:42", "0:00:34:57", "0:00:34:71", "0:00:34:85", "0:00:35:00", 
    "0:00:35:14", "0:00:35:28", "0:00:35:42", "0:00:35:57", "0:00:35:71", 
    "0:00:35:85", "0:00:36:00", "0:00:36:14", "0:00:36:28", "0:00:36:42", 
    "0:00:36:57", "0:00:36:71", "0:00:36:85", "0:00:37:00", "0:00:37:14", 
    "0:00:37:28", "0:00:37:42", "0:00:37:57", "0:00:37:71", "0:00:37:85", 
    "0:00:38:00", "0:00:38:14", "0:00:38:28", "0:00:38:42", "0:00:38:57", 
    "0:00:38:71", "0:00:38:85", "0:00:39:00", "0:00:39:14", "0:00:39:28", 
    "0:00:39:42", "0:00:39:57", "0:00:39:71", "0:00:39:85", "0:00:40:00", 
    "0:00:40:14", "0:00:40:28", "0:00:40:42", "0:00:40:57", "0:00:40:71", 
    "0:00:40:85", "0:00:41:00", "0:00:41:14", "0:00:41:28", "0:00:41:42", 
    "0:00:41:57", "0:00:41:71", "0:00:41:85"), class = "factor")), .Names = c("Caja", 
"x", "y", "t"), row.names = c(NA, 294L), class = "data.frame")

For the plot I use

ggplot(data=df,aes(x,y)) + facet_wrap(~Caja) +
  stat_density2d(aes(fill=..level..,alpha=..level..),geom='polygon',colour='black') +
  scale_fill_continuous(low="green",high="red") +
  geom_point()+guides(alpha="none")

enter image description here

When I plot only caja4 data

ggplot(data=caja4,aes(x,y)) + facet_wrap(~Caja) +
  stat_density2d(aes(fill=..level..,alpha=..level..),geom='polygon',colour='black') + 
  scale_fill_continuous(low="green",high="red") +
  geom_point()+guides(alpha="none")

enter image description here

This makes interpretation more easy although if you look at the line plot, things are a little bit different

ggplot(caja4,aes(x,y))+geom_point()+geom_path(col="red")+theme_classic()

enter image description here

I would like to have free density scale for the facets but have something that relies more to the line plot.


Solution

  • General comments

    Ok, a bunch of things to discuss here I think:

    1. You can use scales = 'free' in your facet call to better align your plotting space with the data.

    2. You cannot vary the density scale between facets. This is because the facets are generally meant to represent different groups using common aesthetically mappings. You could make separate figures instead, and stick them together (with for example the cowplot package).

    3. The polygons get cut off in your plot, leaving you with a disappointing result. I would prefer to use geom_tile to visualize the density of points

    4. As MLavoie pointed out, you'll want to use geom_path instead of geom_line.

    5. That color scale is not so great. For example, it performs really poorly for colorblind people. I would recommend the viridis color scale (see below).

    6. If the units for the x and y axis are the same and meaningful (cm, or pixels perhaps) you want to ensure they are represented in the same way. You can use coord_equal() for that.

    Making a nice plot for one trial

    Here is some example code and a plot to combine this (I only have data for Caja 4):

    library(viridis)
    
    ggplot(caja4, aes(x,y)) +
      stat_density2d(geom = 'tile', aes(fill = ..density..), contour = FALSE) +
      geom_point() + 
      geom_path() +
      scale_fill_viridis() +
      coord_equal() +
      theme_minimal()
    

    enter image description here

    If you do want to use the contour polygons, you have to manually expand the axes to avoid clipping of the polygons (or you have close the polygons yourself):

    ggplot(caja4, aes(x,y)) +
      stat_density2d(geom = 'polygon', aes(fill = ..level..), contour = TRUE) +
      geom_point() + 
      geom_path() +
      scale_fill_viridis() +
      coord_equal() +
      theme_minimal() +
      xlim(-60, 40) +
      ylim(-50, 170)
    

    enter image description here

    Combining different trials

    Instead of facets, we can use figure panels (see point 2 above). I find the cowplot package really useful for this. Below is some example code to easily create a composite figure. (Note that I used log(..density..) here for a different scaling of the colors.)

    # Make data with three cajas (which only differ in x and y range here)
    library(dplyr)
    
    xy <- select(caja4, x, y)
    cajas <- bind_rows('1' = xy, '2' = xy * 2, '3' = xy / 2, .id = 'Caja')
    
    # Create ggplot objects for each caja
    plots <- lapply(split(cajas, cajas$Caja),
                    function(XX) {
                      plot = ggplot(XX, aes(x,y)) +
                        stat_density2d(geom = 'tile', aes(fill = log(..density..)), contour = FALSE) +
                        geom_point() + 
                        geom_path() +
                        scale_fill_viridis() +
                        coord_equal() +
                        theme_minimal()
                    } )
    
    plot_grid(plotlist = plots, nrow = 1, labels = 1:length(plots))
    

    Which results in:

    enter image description here