Диаграмма рассеяния с маргинальными гистограммами в 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 ответов:
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))
Это не совсем отзывчивый ответ, но это очень просто. Это иллюстрирует альтернативный метод для отображения предельных плотностей, а также как использовать Альфа-уровни для графического вывода, который поддерживает прозрачность:
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
Это может быть немного поздно, но я решил сделать пакет (
ggExtra
) для этого, так как он включает в себя немного кода и может быть утомительно писать. Пакет также пытается решить некоторые общие проблемы, такие как обеспечение того, что даже если есть заголовок или текст увеличен, графики все равно будут встроены друг в друга.основная идея похожа на то, что ответы здесь давал, но это немного не то. Вот пример того, как добавить маргинальные гистограммы в случайный набор из 1000 очков. Надеюсь, это упростит добавление гистограмм/плотностных графиков в будущем.
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")
одно добавление, как раз сохранить некоторое ища время для людей делая это после нас.
легенды, метки осей, тексты осей, галочки заставляют сюжеты отдаляться друг от друга, поэтому ваш сюжет будет выглядеть уродливым и непоследовательным.
вы можете исправить это, используя некоторые из этих настроек темы,
+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))
Так что результаты будут выглядеть ОК:
просто очень незначительная вариация на ответ 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))
поскольку не было удовлетворительного решения для такого рода сюжета при сравнении разных групп, я написал функции для этого.
Он работает как для сгруппированных, так и для негруппированных данных и принимает дополнительные графические параметры:
marginal_plot(x = iris$Sepal.Width, y = iris$Sepal.Length)
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)
я нашел пакет (
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))
который отлично работал для меня:
вы можете легко создавать привлекательные диаграммы рассеяния с маргинальными гистограммами, используя 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 )
или немного более привлекательным (по умолчанию) 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) )
обновление:
как предложил @aickley я использовал версию развития для создания сюжета.