Идеально выровняйте графики плотности для графика рассеяния с помощью коровьего графика

Я пытаюсь построить функцию для двумерного построения графика, которая, принимая две переменные, может представлять предельную диаграмму рассеяния и два графика боковой плотности.

Проблема в том, что график плотности справа не совпадает с нижней осью.

Вот пример данных:

g1 = c(rnorm(200, mean=350, sd=100), rnorm(200, mean=700, sd=100))
g2 = c(rnorm(200, mean=350, sd=100), rnorm(200, mean=500, sd=100))
df_exp = data.frame(var1=log2(g1 + 1) , var2=log2(g2 + 1))

Вот функция:

    bivariate_plot <- function(df, var1, var2, density = T, box = F) {
    require(ggplot2)
    require(cowplot)
    scatter = ggplot(df, aes(eval(parse(text = var1)), eval(parse(text = var2)), color = "red")) +
            geom_point(alpha=.8)

    plot1 = ggplot(df, aes(eval(parse(text = var1)), fill = "red")) + geom_density(alpha=.5) 
    plot1 = plot1 + ylab("G1 density")

    plot2 = ggplot(df, aes(eval(parse(text = var2)),fill = "red")) + geom_density(alpha=.5) 
    plot2 = plot2 + ylab("G2 density")

    plot_grid(scatter, plot1, plot2, nrow=1, labels=c('A', 'B', 'C')) #Or labels="AUTO"


    # Avoid displaying duplicated legend
    plot1 = plot1 + theme(legend.position="none")
    plot2 = plot2 + theme(legend.position="none")

    # Homogenize scale of shared axes
    min_exp = min(df[[var1]], df[[var2]]) - 0.01
    max_exp = max(df[[var1]], df[[var2]]) + 0.01
    scatter = scatter + ylim(min_exp, max_exp)
    scatter = scatter + xlim(min_exp, max_exp)
    plot1 = plot1 + xlim(min_exp, max_exp)
    plot2 = plot2 + xlim(min_exp, max_exp)
    plot1 = plot1 + ylim(0, 2)
    plot2 = plot2 + ylim(0, 2)


    first_row = plot_grid(scatter, labels = c('A'))
    second_row = plot_grid(plot1, plot2, labels = c('B', 'C'), nrow = 1)
    gg_all = plot_grid(first_row, second_row, labels=c('', ''), ncol=1)

    # Display the legend
    scatter = scatter + theme(legend.justification=c(0, 1), legend.position=c(0, 1))



    # Flip axis of gg_dist_g2
    plot2 = plot2 + coord_flip()

    # Remove some duplicate axes
    plot1 = plot1 + theme(axis.title.x=element_blank(),
                          axis.text=element_blank(),
                          axis.line=element_blank(),
                          axis.ticks=element_blank())

    plot2 = plot2 + theme(axis.title.y=element_blank(),
                          axis.text=element_blank(),
                          axis.line=element_blank(),
                          axis.ticks=element_blank())

    # Modify margin c(top, right, bottom, left) to reduce the distance between plots
    #and align G1 density with the scatterplot
    plot1 = plot1 + theme(plot.margin = unit(c(0.5, 0, 0, 0.7), "cm"))
    scatter = scatter + theme(plot.margin = unit(c(0, 0, 0.5, 0.5), "cm"))
    plot2 = plot2 + theme(plot.margin = unit(c(0, 0.5, 0.5, 0), "cm"))

    # Combine all plots together and crush graph density with rel_heights
    first_col = plot_grid(plot1, scatter, ncol = 1, rel_heights = c(1, 3))
    second_col = plot_grid(NULL, plot2, ncol = 1, rel_heights = c(1, 3))
    perfect = plot_grid(first_col, second_col, ncol = 2, rel_widths = c(3, 1),
                        axis = "lrbl", align = "hv")

    print(perfect)
}

А вот и призыв к построению:

bivariate_plot(df = df_exp, var1 = "var1", var2 = "var2")

Важно отметить, что эта проблема выравнивания всегда присутствует даже при изменении данных.

введите здесь описание изображения

Вот что случилось с моими настоящими данными:  введите описание изображения здесь


person Seymour    schedule 12.01.2018    source источник
comment
Когда я запускаю ваш код, я этого не понимаю. График плотности справа совпадает с нижней осью.   -  person MLavoie    schedule 12.01.2018
comment
Я использую R studio, поэтому я вижу вашу ошибку на графике в правом нижнем углу. Но когда я нажимаю кнопку увеличения, появляется всплывающее окно, а затем графика в порядке. Вы пробовали сохранить графику и посмотреть, как она выглядит?   -  person MLavoie    schedule 12.01.2018
comment
Я загрузил сохраненную графику!   -  person Seymour    schedule 12.01.2018
comment
Опять же, нормально, когда коплю. Вам просто нужно изменить размер (увеличить) вашего изображения.   -  person MLavoie    schedule 12.01.2018
comment
Итак, вы говорите, что мне нужно как сделать окна графиков в R studio максимальным размером, так и вставить код для сохранения ggplot в функции?   -  person Seymour    schedule 12.01.2018
comment
попробуйте что-нибудь вроде этого (рисунок будет сохранен в вашем рабочем каталоге): png (testing, res = 600, height = 6.5, width = 8, units = in) bivariate_plot (df = df_exp, var1 = var1, var2 = var2) dev.off ()   -  person MLavoie    schedule 12.01.2018
comment
это своего рода улучшение, потому что: A) сюжет должен быть идеальным B) я хочу видеть его правильно в R studio, а не открывать каждый раз .png   -  person Seymour    schedule 12.01.2018
comment
Обычно мы просим предоставить минимальный воспроизводимый пример, чтобы изолировать конкретную проблему. Ваш пример воспроизводимый, но не минимальный. Есть код, который не имеет никакого эффекта (например, создание gg_all) и код, который явно неверен (назначение цвета внутри оператора aes()). Кроме того, объединение всего в функцию создает дополнительный уровень сложности. Проблема в том, что он не работает внутри функции, или это не связано? Если последнее, зачем писать функцию?   -  person Claus Wilke    schedule 13.01.2018
comment
Я написал его внутри функции, потому что хочу иметь возможность использовать его для простого построения диаграммы рассеяния для многих различных переменных. Кроме того, я хотел бы иметь возможность добавлять граничный график, такой как плотность, гистограмма или коробчатые диаграммы. Спасибо за исправление   -  person Seymour    schedule 14.01.2018
comment
В следующий раз буду намного лаконичнее, избегая несущественного момента для решения задачи.   -  person Seymour    schedule 14.01.2018


Ответы (2)


В вашем коде так много ошибок, что я не знаю, с чего начать. Приведенный ниже код исправляет их в той степени, в которой я понимаю, каков ожидаемый результат.

g1 = c(rnorm(200, mean=350, sd=100), rnorm(200, mean=700, sd=100))
g2 = c(rnorm(200, mean=350, sd=100), rnorm(200, mean=500, sd=100))
df_exp = data.frame(var1=log2(g1 + 1) , var2=log2(g2 + 1))


bivariate_plot <- function(df, var1, var2, density = T, box = F) {
  require(ggplot2)
  require(cowplot)
  scatter = ggplot(df, aes_string(var1, var2)) +
    geom_point(alpha=.8, color = "red")

  plot1 = ggplot(df, aes_string(var1)) + geom_density(alpha=.5, fill = "red") 
  plot1 = plot1 + ylab("G1 density")

  plot2 = ggplot(df, aes_string(var2)) + geom_density(alpha=.5, fill = "red") 
  plot2 = plot2 + ylab("G2 density")

  # Avoid displaying duplicated legend
  plot1 = plot1 + theme(legend.position="none")
  plot2 = plot2 + theme(legend.position="none")

  # Homogenize scale of shared axes
  min_exp = min(df[[var1]], df[[var2]]) - 0.01
  max_exp = max(df[[var1]], df[[var2]]) + 0.01
  scatter = scatter + ylim(min_exp, max_exp)
  scatter = scatter + xlim(min_exp, max_exp)
  plot1 = plot1 + xlim(min_exp, max_exp)
  plot2 = plot2 + xlim(min_exp, max_exp)
  plot1 = plot1 + ylim(0, 2)
  plot2 = plot2 + ylim(0, 2)

  # Flip axis of gg_dist_g2
  plot2 = plot2 + coord_flip()

  # Remove some duplicate axes
  plot1 = plot1 + theme(axis.title.x=element_blank(),
                        axis.text=element_blank(),
                        axis.line=element_blank(),
                        axis.ticks=element_blank())

  plot2 = plot2 + theme(axis.title.y=element_blank(),
                        axis.text=element_blank(),
                        axis.line=element_blank(),
                        axis.ticks=element_blank())

  # Modify margin c(top, right, bottom, left) to reduce the distance between plots
  #and align G1 density with the scatterplot
  plot1 = plot1 + theme(plot.margin = unit(c(0.5, 0, 0, 0.7), "cm"))
  scatter = scatter + theme(plot.margin = unit(c(0, 0, 0.5, 0.5), "cm"))
  plot2 = plot2 + theme(plot.margin = unit(c(0, 0.5, 0.5, 0), "cm"))

  # Combine all plots together and crush graph density with rel_heights
  perfect = plot_grid(plot1, NULL, scatter, plot2,
                      ncol = 2, rel_widths = c(3, 1), rel_heights = c(1, 3))

  print(perfect)
}

bivariate_plot(df = df_exp, var1 = "var1", var2 = "var2")

введите здесь описание изображения

person Claus Wilke    schedule 13.01.2018
comment
@Seymour Обратите внимание, что все еще существует разрыв между диаграммой рассеяния и диаграммами плотности. Этот пробел можно устранить, установив для параметра expand шкалы y значение 0. - person Claus Wilke; 14.01.2018
comment
Разрыв не имеет значения. Что действительно было важно, так это выравнивание точек диаграммы рассеяния и граничных участков. Тем не менее, спасибо, что объяснили мне также, как настроить этот параметр. Очень добрый! - person Seymour; 14.01.2018
comment
Мистер Клаус Уилке, вы понимаете, почему, если я удалю плотность G1 и плотность G2 таким образом, чтобы получить чистые граничные участки (без метки), они больше не будут выровнены. Как я могу решить эту проблему? - person Seymour; 15.01.2018
comment
да. Если вам нужны чистые маргиналы без осей, используйте ggarrange из пакета egg вместо plot_grid(). Или используйте подход axis_canvas из cowplot: lreding.com/nonstandard_deviations/2017/08 / 19 / cowmarg - person Claus Wilke; 15.01.2018

Этого можно легко добиться с помощью пакета ggExtra, а не развертывать собственное решение.

library(ggExtra)
library(ggplot2)
g1 = c(rnorm(200, mean=350, sd=100), rnorm(200, mean=700, sd=100))
g2 = c(rnorm(200, mean=350, sd=100), rnorm(200, mean=500, sd=100))
df_exp = data.frame(var1=log2(g1 + 1) , var2=log2(g2 + 1))
g <- ggplot(df_exp, aes(x=var1, y=var2)) + geom_point()
ggMarginal(g) 

Выход:

Предельные плотности

person alan ocallaghan    schedule 13.01.2018
comment
Спасибо. Я не использовал ggmarginal, потому что мне не нравится, как реализованы блочные диаграммы - person Seymour; 14.01.2018
comment
Можете быть более конкретными? Возможно изменение некоторых аспектов окраинных участков. - person alan ocallaghan; 14.01.2018
comment
Извините за поздний ответ. Критическим моментом является то, что ggMarginal создает сам сюжет и не позволяет вам создавать свои собственные предельные сюжеты. Что касается boxplot из ggMarginal, минимальное значение - это самый низкий ус, а максимальное значение - это самый высокий ус, поэтому выбросы, обнаруженные с использованием правила Тьюки, не отображаются в виде отдельных точек за пределами усов. - person Seymour; 15.01.2018
comment
Используя v0.7 ggExtra, я вижу выбросы (ggMarginal(g, type="box")). Я также могу удалить их следующим образом: ggMarginal(g, type="box", outlier.shape=NA) - person alan ocallaghan; 15.01.2018