Диаграмма рассеяния с маргинальными гистограммами в ggplot2


есть ли способ создания диаграмм рассеяния с маргинальными гистограммами, как в примере ниже в ggplot2? В Matlab это scatterhist() функция и существуют эквиваленты для R также. Однако, я не видел его в ggplot2.

Я начал попытку, создав отдельные графики, но не знаю, как правильно их организовать.

 require(ggplot2)
 x<-rnorm(300)
 y<-rt(300,df=2)
 xy<-data.frame(x,y)
     xhist <- qplot(x, geom="histogram") + scale_x_continuous(limits=c(min(x),max(x))) + opts(axis.text.x = theme_blank(), axis.title.x=theme_blank(), axis.ticks = theme_blank(), aspect.ratio = 5/16, axis.text.y = theme_blank(), axis.title.y=theme_blank(), background.colour="white")
     yhist <- qplot(y, geom="histogram") + coord_flip() + opts(background.fill = "white", background.color ="black")

     yhist <- yhist + scale_x_continuous(limits=c(min(x),max(x))) + opts(axis.text.x = theme_blank(), axis.title.x=theme_blank(), axis.ticks = theme_blank(), aspect.ratio = 16/5, axis.text.y = theme_blank(), axis.title.y=theme_blank() )


     scatter <- qplot(x,y, data=xy)  + scale_x_continuous(limits=c(min(x),max(x))) + scale_y_continuous(limits=c(min(y),max(y)))
none <- qplot(x,y, data=xy) + geom_blank()

и организовать их с помощью функции posted здесь. Но чтобы сделать длинную историю короткой: Есть ли способ создания этих графиков?

8 116

8 ответов:

The gridExtra пакет должен работать здесь. Начните с создания каждого из объектов ggplot:

hist_top <- ggplot()+geom_histogram(aes(rnorm(100)))
empty <- ggplot()+geom_point(aes(1,1), colour="white")+
         theme(axis.ticks=element_blank(), 
               panel.background=element_blank(), 
               axis.text.x=element_blank(), axis.text.y=element_blank(),           
               axis.title.x=element_blank(), axis.title.y=element_blank())

scatter <- ggplot()+geom_point(aes(rnorm(100), rnorm(100)))
hist_right <- ggplot()+geom_histogram(aes(rnorm(100)))+coord_flip()

затем используйте сетку.аранжируйте функцию:

grid.arrange(hist_top, empty, scatter, hist_right, ncol=2, nrow=2, widths=c(4, 1), heights=c(1, 4))

plot

Это не совсем отзывчивый ответ, но это очень просто. Это иллюстрирует альтернативный метод для отображения предельных плотностей, а также как использовать Альфа-уровни для графического вывода, который поддерживает прозрачность:

scatter <- qplot(x,y, data=xy)  + 
         scale_x_continuous(limits=c(min(x),max(x))) + 
         scale_y_continuous(limits=c(min(y),max(y))) + 
         geom_rug(col=rgb(.5,0,0,alpha=.2))
scatter

enter image description here

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

основная идея похожа на то, что ответы здесь давал, но это немного не то. Вот пример того, как добавить маргинальные гистограммы в случайный набор из 1000 очков. Надеюсь, это упростит добавление гистограмм/плотностных графиков в будущем.

ссылка на пакет ggExtra

library(ggplot2)
df <- data.frame(x = rnorm(1000, 50, 10), y = rnorm(1000, 50, 10))
p <- ggplot(df, aes(x, y)) + geom_point() + theme_classic()
ggExtra::ggMarginal(p, type = "histogram")

enter image description here

одно добавление, как раз сохранить некоторое ища время для людей делая это после нас.

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

вы можете исправить это, используя некоторые из этих настроек темы,

+theme(legend.position = "none",          
       axis.title.x = element_blank(),
       axis.title.y = element_blank(),
       axis.text.x = element_blank(),
       axis.text.y = element_blank(), 
       plot.margin = unit(c(3,-5.5,4,3), "mm"))

и выровнять весы,

+scale_x_continuous(breaks = 0:6,
                    limits = c(0,6),
                    expand = c(.05,.05))

Так что результаты будут выглядеть ОК:

an example

просто очень незначительная вариация на ответ BondedDust В общем духе предельных показателей распределения.

Эдвардом Тафтом назвал это использование участков ковра "точечно-тире" и имеет пример в VDQI использования осевых линий для указания диапазона каждой переменной. В моем примере метки осей и линий сетки также указывают на распределение данных. Метки расположены по значениям номер пять Тьюки резюме (минимум, Нижний шарнир, медиана, верхний шарнир, максимум), что дает быстрое представление о разбросе каждой переменной.

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

x<-rnorm(300)
y<-rt(300,df=10)
xy<-data.frame(x,y)

require(ggplot2); require(grid)
# make the basic plot object
ggplot(xy, aes(x, y)) +        
  # set the locations of the x-axis labels as Tukey's five numbers   
  scale_x_continuous(limit=c(min(x), max(x)), 
                     breaks=round(fivenum(x),1)) +     
  # ditto for y-axis labels 
  scale_y_continuous(limit=c(min(y), max(y)),
                     breaks=round(fivenum(y),1)) +     
  # specify points
  geom_point() +
  # specify that we want the rug plot
  geom_rug(size=0.1) +   
  # improve the data/ink ratio
  theme_set(theme_minimal(base_size = 18))

enter image description here

поскольку не было удовлетворительного решения для такого рода сюжета при сравнении разных групп, я написал функции для этого.

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

marginal_plot(x = iris$Sepal.Width, y = iris$Sepal.Length)

enter image description here

marginal_plot(x = Sepal.Width, y = Sepal.Length, group = Species, data = iris, bw = "nrd", lm_formula = NULL, xlab = "Sepal width", ylab = "Sepal length", pch = 15, cex = 0.5)

enter image description here

я нашел пакет (ggpubr), который, кажется, работает очень хорошо для этой проблемы и рассматривает несколько возможностей для отображения данных.

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

я сначала установил пакет (он требует devtools)

if(!require(devtools)) install.packages("devtools")
devtools::install_github("kassambara/ggpubr")

для конкретного примера отображения различные гистограммы для разных групп, он упоминает в связи с ggExtra: "одно ограничение ggExtra это то, что он не может справиться с несколькими группами в диаграмме рассеяния и маргинальных участков. В приведенном ниже коде R мы предоставляем решение с использованием cowplot пакета."В моем случае, мне пришлось установить последний пакет:

install.packages("cowplot")

и я последовал этому фрагменту кода:

# Scatter plot colored by groups ("Species")
sp <- ggscatter(iris, x = "Sepal.Length", y = "Sepal.Width",
            color = "Species", palette = "jco",
            size = 3, alpha = 0.6)+
border()                                         
# Marginal density plot of x (top panel) and y (right panel)
xplot <- ggdensity(iris, "Sepal.Length", fill = "Species",
               palette = "jco")
yplot <- ggdensity(iris, "Sepal.Width", fill = "Species", 
               palette = "jco")+
rotate()
# Cleaning the plots
sp <- sp + rremove("legend")
yplot <- yplot + clean_theme() + rremove("legend") 
xplot <- xplot + clean_theme() + rremove("legend")
# Arranging the plot using cowplot
library(cowplot)
plot_grid(xplot, NULL, sp, yplot, ncol = 2, align = "hv", 
      rel_widths = c(2, 1), rel_heights = c(1, 2))

который отлично работал для меня:

Iris установить маргинальные гистограммы рассеивания

enter image description here

вы можете легко создавать привлекательные диаграммы рассеяния с маргинальными гистограммами, используя ggstatsplot (Он также будет соответствовать и описывать модель):

data(iris)

library(ggstatsplot)

ggscatterstats(
  data = iris,                                          
  x = Sepal.Length,                                                  
  y = Sepal.Width,
  xlab = "Sepal Length",
  ylab = "Sepal Width",
  marginal = TRUE,
  marginal.type = "histogram",
  centrality.para = "mean",
  margins = "both",
  title = "Relationship between Sepal Length and Sepal Width",
  messages = FALSE
)

enter image description here

или немного более привлекательным (по умолчанию) ggpubr:

devtools::install_github("kassambara/ggpubr")
library(ggpubr)

ggscatterhist(
  iris, x = "Sepal.Length", y = "Sepal.Width",
  color = "Species", # comment out this and last line to remove the split by species
  margin.plot = "histogram", # I'd suggest removing this line to get density plots
  margin.params = list(fill = "Species", color = "black", size = 0.2)
)

enter image description here

обновление:

как предложил @aickley я использовал версию развития для создания сюжета.