график рассеяния по всем группам для длинного фрейма данных - PullRequest
3 голосов
/ 09 апреля 2019

Я почти уверен, что что-то подобное уже спросили, но я не знаю, как его искать.

Я часто получаю данные в широком формате, как в моем маленьком примере с 3 экспериментами (a-c). Я обычно конвертирую в длинный формат и конвертирую значения некоторой функцией (здесь log2 в качестве примера).

Что я часто хочу делать, так это строить все эксперименты друг против друга, и здесь я ищу удобное решение. Как я могу преобразовать свой фрейм данных, чтобы получить фасеты, например, с a~b, a~c и b~c ...

Пока что я tidy::spread снова получаю данные и 3 раза выполняю команду ggplot с именами отдельных столбцов, такими как x и y. Позже я объединю отдельные графики.

Есть ли более удобный способ?

library(dplyr)
library(tidyr)
library(ggplot2)

df <- data.frame(
  names=letters,
  a=1:26,
  b=1:13,
  c=11:36
)

df %>%
  tidyr::gather(experiment, value, -names) %>%
  mutate(log2.value=log2(value)) 

EDIT
Поскольку я получил очень полезный ответ от @hdkrgr, я немного адаптировал свой код. inner_join был замечательным трюком, который я могу реализовать, чтобы автоматизировать свою идею, но мне все еще не хватает умного фильтра для избавления от лишних данных, поскольку я не хочу строить c~c или b~a, если я уже сюжет a~b. Я решил это сейчас, предоставив соединения, которые я хочу сделать, но может ли кто-нибудь подумать об этом прямолинейном решении? Я не мог придумать что-то, что дает мне уникальное сочетание.

my_pairs <- c('a vs. b', 'a vs. c', 'b vs. c')

df %>%
  as_tibble() %>%
  tidyr::gather(experiment, value, -names) %>%
  mutate(log2.value=log2(value))  %>%
  inner_join(., ., by=c("names")) %>%
  mutate(pairing=sprintf('%s vs. %s', experiment.x, experiment.y)) %>%
  filter(pairing %in% my_pairs) %>% 
  ggplot(aes(log2.value.x, log2.value.y)) + 
  geom_point() + 
  facet_wrap( ~ pairing, labeller=label_both)

Ответы [ 4 ]

4 голосов
/ 09 апреля 2019

Одним из способов, начиная с длинного формата, было бы выполнить самостоятельное объединение длинных данных, чтобы получить все комбинации двух экспериментов в каждой строке:

df %>%
    tidyr::gather(experiment, value, -names) %>%
    mutate(log2.value=log2(value)) %>%
    inner_join(., ., by=c("names")) %>% 
    ggplot(aes(log2.value.x, log2.value.y)) + geom_point() + facet_grid(experiment.y ~ experiment.x)

enter image description here

Редактировать: Чтобы избежать создания избыточных экспериментальных пар, вы можете сделать:

df %>%
    tidyr::gather(experiment, value, -names) %>%
    mutate(log2.value=log2(value)) %>% inner_join(., ., by=c("names")) %>% 
    filter(experiment.x < experiment.y) %>% 
    ggplot(aes(log2.value.x, log2.value.y)) + geom_point() + facet_wrap(~experiment.y + experiment.x)

enter image description here

3 голосов
/ 09 апреля 2019

Это действительно интересно, потому что это на самом деле сложнее, чем кажется на первый взгляд.Одна вещь, которая бросается в глаза, это получение уникальных пар экспериментов - кажется, что вы хотите vs b, но не обязательно b v a a.Для этого вам понадобится уникальный набор экспериментальных пар.

Изначально я пытался работать с вашими данными gather, но понял, что проще начать с широкой версии.Возьмите названия экспериментов из имен столбцов - вы можете сделать это несколькими способами, но я просто взял строки, которые не "names", - и получите их комбинации.Я склеил их вместе, чтобы сделать их немного легче в работе.

library(dplyr)
library(tidyr)
library(ggplot2)

df <- data.frame(
  names=letters,
  a=1:26,
  b=1:13,
  c=11:36
) %>%
  as_tibble()

exp <- stringr::str_subset(names(df), "names", negate = T)

pairs <- combn(exp, 2, paste, simplify = F, collapse = ",") %>%
  unlist()
pairs
#> [1] "a,b" "a,c" "b,c"

Затем для каждой пары извлеките имена связанных столбцов, сделайте небольшое прибавление, чтобы выбрать эти столбцы, выполните преобразование log2что у тебя было.Мне пришлось объездить здесь, чтобы переименовать столбцы с чем-то, на что я мог бы сослаться - я думаю, что в этом нет необходимости, но я не мог заставить мой тидевал работать внутри ggplot aes.Кто-то еще может иметь представление об этом.Затем создайте свой сюжет и соответственно пометьте оси и заголовок.Таким образом, у вас будет список из 3 графиков.

plots <- purrr::map(pairs, function(pair) {
  cols <- strsplit(pair, split = ",", fixed = T)[[1]]
  df %>%
    select(names, !!cols[1], !!cols[2]) %>%
    mutate_at(vars(-names), log2) %>%
    rename(exp1 = !!cols[1], exp2 = !!cols[2]) %>%
    ggplot(aes(x = exp1, y = exp2)) +
      geom_point() +
      labs(x = cols[1], y = cols[2], title = pair)
})

Используйте свой метод выбора, чтобы составить графики так, как вы хотите.Я пошел с cowplot, но мне также нравится пакет patchwork.

cowplot::plot_grid(plotlist = plots, nrow = 1)

2 голосов
/ 09 апреля 2019

Вероятно, это не то, что вам нужно, но если целью является изучение паттерна корреляции между каждой переменной, вы можете рассмотреть ggpairs из пакета GGally. Он предоставляет не только точечные диаграммы, но также оценку и распределение корреляции.

library(GGally)

ggpairs(df[, c("a", "b", "c")])

enter image description here

1 голос
/ 09 апреля 2019

Вы можете начать с создания всех комбинаций с помощью combn, а затем пройти через:

library(purrr)

t(combn(names(df)[-1], 2)) %>% ## get all combinations  
   as.data.frame(stringsAsFactors = FALSE) %>% 
   mutate(l = paste(V1, V2, sep = " vs. ")) %>%
   pmap_dfr(function(V1, V2, l) 
     df %>% 
       select(one_of(c(V1, V2))) %>% ## select the elements given by the combination
       mutate_all(log2) %>%
       setNames(c("x", "y")) %>%
       mutate(experiment = l)) %>%
   ggplot(aes(x, y)) + geom_point() + facet_wrap(~experiment)

Scatterplot

...