项目作者: jhrcook

项目描述 :
在对称矩阵的左上角或右下角绘制两种不同的颜色方案
高级语言: R
项目地址: git://github.com/jhrcook/ggasym.git
创建时间: 2019-02-20T22:07:33Z
项目社区:https://github.com/jhrcook/ggasym

开源协议:Other

下载


ggasym

License: GPL
v3
CRAN
status
CRAN
downloads
R build
status
Coverage
status

Asymmetric Matrix Plotting in ‘ggplot’

‘ggasym’ (pronounced “gg-awesome”) plots a symmetric matrix with three
different fill aesthetics for the top-left and bottom-right triangles
and along the diagonal. It operates within the Grammar of Graphics
paradigm implemented in ‘ggplot2’.

Checkout the documentation and vignettes at the pkgdown website
https://jhrcook.github.io/ggasym/

For information on using ‘ggplot2’, start
here.

Download and Installation

‘ggasym’ is available on CRAN. Use the following command to install.

  1. install.packages("ggasym")

You can download and install the latest development version from the
GitHub repo.

  1. devtools::install_github("jhrcook/ggasym")

And load the package with the standard library function.

  1. library(ggasym)

Basic Usage

Here is a basic example. tib is a “tibble” (i.e.. fancy “data.frame”)
of comparisons between groups “A” through “E”. There are two values to
be plotted, val_1 and val_2, that hold data on the comparison
between g1 and g2. tib is first passed to asymmetrise() to fill
in all the missing combinations between g1 and g2 such that the
symmetric matrix can be built. All added values take the value NA. The
modified data table is finally passed to ggplot() and geom_asymmat()
is added on. Here, asymmetrise() added the rows where g1 and g2
are equal, thus will fill the diagonal. I set these values to val_3.

  1. tib <- tibble(
  2. g1 = c("A", "A", "A", "A", "B", "B", "B", "C", "C", "D"),
  3. g2 = c("B", "C", "D", "E", "C", "D", "E", "D", "E", "E"),
  4. val_1 = seq(1, 10, 1),
  5. val_2 = rnorm(10, mean = 0, sd = 3)
  6. )
  7. tib <- asymmetrise(tib, g1, g2)
  8. tib$val_3 <- runif(nrow(tib))
  9. ggplot(tib, aes(x = g1, y = g2)) +
  10. geom_asymmat(aes(fill_tl = val_1, fill_br = val_2, fill_diag = val_3)) +
  11. scale_fill_tl_gradient(low = "lightpink", high = "tomato") +
  12. scale_fill_br_gradient(low = "lightblue1", high = "dodgerblue") +
  13. scale_fill_diag_gradient(low = "yellow", high = "orange3")

New Aesthetics

The new aesthetics fill_tl, fill_br, and fill_diag behave just
like the normal fill, except that they correspond to the top-left
(“tl”) and bottom-right (“br”) triangles of the matrix, respectively.
This package also includes analogous functions for scaling the fill
colors such as scale_fill_tl_gradient2() and
scale_fill_br_gradientn() that operate just as expected when using
‘ggplot2’.

  1. ggplot(tib, aes(x = g1, y = g2)) +
  2. geom_asymmat(aes(fill_tl = val_1, fill_br = val_2, fill_diag = val_3)) +
  3. scale_fill_tl_gradient(low = "lightpink", high = "tomato") +
  4. scale_fill_br_gradient2(low = "orange", mid = "white", high = "dodgerblue") +
  5. scale_fill_diag_gradientn(colors = rainbow(25))

Adjusting Colorbars

Of note, with three colorbars, it may be useful to control their
position and other properties. This can be done just like normal in
‘ggplot2’ by passing the correct values to the guide parameter in
scale_fill_*_gradient() (original
documentation
).
Below are a few of the options where I put the bars horizontal, adjust
the ordering, and put the title above each.

  1. ggplot(tib, aes(x = g1, y = g2)) +
  2. geom_asymmat(aes(fill_tl = val_1, fill_br = val_2, fill_diag = val_3)) +
  3. scale_fill_tl_gradient(
  4. low = "lightpink", high = "tomato",
  5. guide = guide_colourbar(
  6. direction = "horizontal",
  7. order = 1,
  8. title.position = "top"
  9. )
  10. ) +
  11. scale_fill_br_gradient2(
  12. low = "orange", mid = "white", high = "dodgerblue",
  13. guide = guide_colourbar(
  14. direction = "horizontal",
  15. order = 3,
  16. title.position = "top"
  17. )
  18. ) +
  19. scale_fill_diag_gradientn(
  20. colors = rainbow(25),
  21. guide = guide_colourbar(
  22. direction = "horizontal",
  23. order = 2,
  24. title.position = "top"
  25. )
  26. )

Full ggplot2 integration

Since the new geom is a normal ‘ggplot2’ object, it can be introduced
into a standard ‘ggplot2’ workflow. Note that the labels can be adjusted
like normal using the labs function and using the fill_tl,
fill_br, and fill_diag arguments.

  1. ggplot(tib, aes(x = g1, y = g2)) +
  2. geom_asymmat(aes(
  3. fill_tl = log(val_1),
  4. fill_br = val_2,
  5. fill_diag = val_3
  6. )) +
  7. scale_fill_tl_gradient(
  8. low = "lightpink", high = "tomato",
  9. guide = guide_colourbar(
  10. direction = "horizontal",
  11. order = 1,
  12. title.position = "top"
  13. )
  14. ) +
  15. scale_fill_br_gradient(
  16. low = "lightblue1", high = "dodgerblue",
  17. guide = guide_colourbar(
  18. direction = "horizontal",
  19. order = 3,
  20. title.position = "top"
  21. )
  22. ) +
  23. scale_fill_diag_gradient(
  24. low = "grey80", high = "grey20",
  25. guide = guide_colourbar(
  26. direction = "horizontal",
  27. order = 2,
  28. title.position = "top"
  29. )
  30. ) +
  31. labs(
  32. fill_tl = "top-left fill",
  33. fill_br = "bottom-right fill",
  34. fill_diag = "diagonal fill",
  35. title = "Example of ggasym"
  36. ) +
  37. theme_bw() +
  38. theme(
  39. axis.title = element_blank(),
  40. plot.title = element_text(hjust = 0.5),
  41. panel.background = element_rect(fill = "grey70"),
  42. panel.grid = element_blank()
  43. ) +
  44. scale_x_discrete(expand = c(0, 0)) +
  45. scale_y_discrete(expand = c(0, 0))

Faceting

If you have multiple categories, faceting works as expected. The only
difference is in the preparation of the data table: you must
group_by() the value(s) you will facet by before passing to
asymmetrise(). This is shown below.

  1. tib <- tibble(
  2. g1 = rep(c("A", "A", "B"), 2),
  3. g2 = rep(c("B", "C", "C"), 2),
  4. val_1 = seq(1, 6),
  5. val_2 = rnorm(6),
  6. grps = c(1, 1, 1, 2, 2, 2)
  7. )
  8. tib
  9. #> # A tibble: 6 x 5
  10. #> g1 g2 val_1 val_2 grps
  11. #> <chr> <chr> <int> <dbl> <dbl>
  12. #> 1 A B 1 0.0746 1
  13. #> 2 A C 2 -1.99 1
  14. #> 3 B C 3 0.620 1
  15. #> 4 A B 4 -0.0561 2
  16. #> 5 A C 5 -0.156 2
  17. #> 6 B C 6 -1.47 2

Grouping first by grps, the tibble is asymmetrized while retaining the
grps assignments. I then added values to the diagonal.

  1. tib <- tib %>%
  2. group_by(grps) %>%
  3. asymmetrise(g1, g2) %>%
  4. ungroup()
  5. tib <- tib %>% mutate(val_3 = ifelse(g1 == g2, runif(nrow(tib)), NA))
  6. tib
  7. #> # A tibble: 18 x 6
  8. #> grps g1 g2 val_1 val_2 val_3
  9. #> <dbl> <chr> <chr> <int> <dbl> <dbl>
  10. #> 1 1 A B 1 0.0746 NA
  11. #> 2 1 A C 2 -1.99 NA
  12. #> 3 1 B C 3 0.620 NA
  13. #> 4 1 B A 1 0.0746 NA
  14. #> 5 1 C A 2 -1.99 NA
  15. #> 6 1 C B 3 0.620 NA
  16. #> 7 1 A A NA NA 0.459
  17. #> 8 1 B B NA NA 0.332
  18. #> 9 1 C C NA NA 0.651
  19. #> 10 2 A B 4 -0.0561 NA
  20. #> 11 2 A C 5 -0.156 NA
  21. #> 12 2 B C 6 -1.47 NA
  22. #> 13 2 B A 4 -0.0561 NA
  23. #> 14 2 C A 5 -0.156 NA
  24. #> 15 2 C B 6 -1.47 NA
  25. #> 16 2 A A NA NA 0.839
  26. #> 17 2 B B NA NA 0.347
  27. #> 18 2 C C NA NA 0.334
  1. ggplot(tib, aes(x = g1, y = g2)) +
  2. geom_asymmat(aes(
  3. fill_tl = log(val_1),
  4. fill_br = val_2,
  5. fill_diag = val_3
  6. )) +
  7. scale_fill_tl_gradient(
  8. low = "lightpink", high = "tomato",
  9. guide = guide_colourbar(
  10. direction = "horizontal",
  11. order = 1,
  12. title.position = "top"
  13. )
  14. ) +
  15. scale_fill_br_gradient(
  16. low = "lightblue1", high = "dodgerblue",
  17. guide = guide_colourbar(
  18. direction = "horizontal",
  19. order = 3,
  20. title.position = "top"
  21. )
  22. ) +
  23. scale_fill_diag_gradient(
  24. low = "grey80", high = "grey20",
  25. guide = guide_colourbar(
  26. direction = "horizontal",
  27. order = 2,
  28. title.position = "top"
  29. )
  30. ) +
  31. labs(
  32. fill_tl = "top-left fill",
  33. fill_br = "bottom-right fill",
  34. fill_diag = "diagonal fill",
  35. title = "Example of faceting with ggasym"
  36. ) +
  37. theme_bw() +
  38. theme(
  39. axis.title = element_blank(),
  40. plot.title = element_text(hjust = 0.5),
  41. panel.background = element_rect(fill = "grey70"),
  42. panel.grid = element_blank()
  43. ) +
  44. scale_x_discrete(expand = c(0, 0)) +
  45. scale_y_discrete(expand = c(0, 0)) +
  46. facet_grid(. ~ grps)


Statistical Test Wrapper

I created a wrapper for handling the results of a statistical test to
produce a tibble ready to be plotted with ggasym. Here is a brief
example - a more detailed example is shown in the vignette “Statistical
Test
Plotting”
.
Here I test if the median sale price of houses in Austin, Texas is
different between any of the years (for more information on the data
source: ?ggplot2::txhousing).

  1. tib <- ggplot2::txhousing %>%
  2. filter(city == "Austin") %>%
  3. mutate(year = as.character(year))
  4. aov_res <- aov(median ~ year, data = tib)
  5. broom::tidy(aov_res)
  6. #> # A tibble: 2 x 6
  7. #> term df sumsq meansq statistic p.value
  8. #> <chr> <dbl> <dbl> <dbl> <dbl> <dbl>
  9. #> 1 year 15 169514394144. 11300959610. 213. 4.29e-102
  10. #> 2 Residuals 171 9077385000. 53084123. NA NA

Before plotting, the results of the Tukey post-hoc test are passed to
asymmetrise_stats() that prepares the data for geom_asymmat(). The
resulting tibble is then plotted and styled in ‘ggplot2’.

  1. asymmat_tib <- asymmetrise_stats(TukeyHSD(aov_res))
  2. ggplot(asymmat_tib, aes(x = x, y = y)) +
  3. geom_asymmat(aes(
  4. fill_tl = estimate,
  5. fill_br = -log10(adj.p.value + 0.0000001)
  6. )) +
  7. scale_fill_tl_gradient2(low = "dodgerblue", high = "tomato") +
  8. scale_fill_br_distiller(type = "seq", palette = "Greens", direction = 1) +
  9. labs(
  10. title = "Median House Prices in Austin",
  11. fill_tl = "diff. in\nmean values",
  12. fill_br = "-log10( adj. p-value )"
  13. ) +
  14. theme(
  15. panel.background = element_rect(fill = "grey75"),
  16. panel.grid = element_blank()
  17. ) +
  18. scale_x_discrete(expand = c(0, 0)) +
  19. scale_y_discrete(expand = c(0, 0))


Thank yous

I would like to thank the team behind
‘ggplot2’ for creating a flexible and
powerful package for the R community.

If you see any mistakes (including small typos) please open an
issue and leave a quick
statement. Do not worry about appearing annoying.