Ggplot2'de marjinal histogramlı dağılım grafiği


137

Aşağıdaki örnekteki gibi marjinal histogramlı dağılım grafikleri oluşturmanın bir yolu var mı ggplot2? Matlab'da bu scatterhist()işlevdir ve R için de eşdeğerleri vardır. Ancak, ggplot2 için görmedim.

marjinal histogramlı dağılım grafiği

Tek grafikleri oluşturarak bir girişimde bulundum, ancak bunları nasıl düzgün bir şekilde ayarlayacağımı bilmiyorum.

 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()

ve burada yayınlanan işlevle düzenleme . Fakat uzun hikayeyi kısaltmak gerekirse: Bu grafikleri yaratmanın bir yolu var mı?


@DWin sağ teşekkür ederim - ama bence soruma verdiğim çözüm hemen hemen bu. Ancak, geom_rag () çok aşağıda sizin tarafınızdan verilen düşünüyorum gibi!
Seb

1
aynı konuyu içeren yeni bir blog gönderisinden: blog.mckuhn.de/2009/09/learning-ggplot2-2d-plot-with.html da oldukça hoş görünüyor :)
Seb

Grafik Galerisi için yeni web sitesi: gallery.r-enthusiasts.com
IRTFM

@Seb mantıklı olduğunu düşünüyorsanız, "kabul edilen cevabı" ggExtra paketi ile değiştirmeyi düşünebilirsiniz
DeanAttali

Yanıtlar:


93

gridExtraPaket burada çalışması gerekir. Her bir ggplot nesnesini yaparak başlayın:

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()

Ardından grid.arrange işlevini kullanın:

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

arsa


6
Yerleşimi göstermek için 1+, ancak iç dağılımın marjinal histogramlarla "hizalanmasını" istiyorsanız rastgele örneklemeyi yeniden yapmamalısınız.
IRTFM

1
Haklısın. Yine de aynı dağılımdan örneklenmişlerdir, bu nedenle marjinal histogramlar teorik olarak dağılım grafiğiyle eşleşmelidir.
oeo4b

8
"Teoride" asimptotik olarak "eşleşme" olacaklardır; pratikte kaç kez eşleşecekleri son derece azdır. Verilen örneği xy <- data.frame(x=rnorm(300), y=rt(300,df=2) )kullanmak data=xyve ggplot çağrılarında kullanmak çok kolaydır .
IRTFM

7
Parsel eksenleri genellikle tam olarak hizalanmadığı için bu çözümü tavsiye etmem. Umarım ggplot2'nin gelecekteki sürümleri eksenleri hizalamayı kolaylaştıracak, hatta bir çizim panelinin kenarlarında özel notlara izin verecektir (kafesdeki özelleştirilmiş ikincil eksen işlevleri gibi).
baptiste

9
Hayır, genel olarak yapmazlardı. ggplot2 şu anda eksen etiketlerinin vb. boyutuna bağlı olarak değişen değişen bir panel genişliği çıkarır.
baptiste

115

Bu tamamen duyarlı bir cevap değil ama çok basit. Kenar boşluklarını görüntülemek için alternatif bir yöntemi ve saydamlığı destekleyen grafik çıktısı için alfa seviyelerinin nasıl kullanılacağını gösterir:

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

resim açıklamasını buraya girin


5
Yoğunluğu göstermenin ilginç bir yolu. Bu yanıtı eklediğiniz için teşekkür ederiz. :)
Michelle

21
Bu yöntemin marjinal histogramlar koymaktan çok daha yaygın olduğu belirtilmelidir. Aslında, marjinal tarihçeleri olan yayınlanmış bir makaleyi hiç görmediğim yayınlanmış makalelerde halı arazileri yaygındır.
Xu Wang

Çok ilginç ve sezgisel alternatif cevap! Ve çok basit! Doğru cevaptan daha fazla oy alması şaşırtıcı değil. Anladığım kadarıyla, bu aslında tek boyutlu bir ısı haritasıdır : halılar kalabalık olan her yerde daha koyudur. Tek endişem, ısı haritasının çözünürlüğü histogram kadar yüksek değil. Örneğin. arsa küçük olduğunda, tüm halılar birlikte sıkılır ve bu da dağılımı algılamayı zorlaştırır. Histogram sınırlamadan muzdarip olmasa da. Fikir için teşekkürler!
HongboZhu

94

Bu biraz geç olabilir, ama bunun için bir paket ( ggExtra) yapmaya karar verdim çünkü biraz kod içeriyordu ve yazmak sıkıcı olabilir. Paket ayrıca, bir başlık veya metin büyütülmüş olsa bile, grafiklerin hala birbiriyle satır içinde olmasını sağlamak gibi bazı genel sorunları ele almaya çalışır.

Temel fikir, buradaki yanıtların verdiği şeye benzer, ancak bunun biraz ötesine geçer. İşte 1000 noktadan oluşan rasgele bir kümeye marjinal histogramların nasıl ekleneceğine dair bir örnek. Umarım bu gelecekte histogramlar / yoğunluk grafikleri eklemeyi kolaylaştırır.

GgExtra paketine bağlantı

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")

resim açıklamasını buraya girin


1
Paket için çok teşekkürler. Kutunun dışında çalışır!
heroxbd

Bu paketle renge göre gruplandırılmış nesneler için marjinal yoğunluk grafikleri çizmek mümkün müdür?
GegznaV

Hayır, böyle bir mantığı yok
DeanAttali

1
@jjrr Neyin işe yaramadığından ve hangi sorunlardan yaşadığınızdan emin değilim, ancak bir not defterinde oluşturma konusunda github'da yeni bir sorun vardı ve bunun da bir çözümü var, bu yararlı olabilir github.com/daattali/ Ekstra / Sayılar / 89
DeanAttali

1
@GegznaV, hala marjinal yoğunluk grafiklerinin renklere göre gruplandırılmasını sağlamanın bir yolunu arıyorsanız, ggExtra 0.9: ggMarginal (p, type = "density", boyut = 5, groupColour = TRUE) ile
MartineJ

46

Bir ek, sadece bizden sonra bunu yapan insanlar için biraz zaman kazanmak için.

Efsaneler, eksen etiketleri, eksen metinleri, keneler arazileri birbirinden uzaklaştırır, böylece grafiğiniz çirkin ve tutarsız görünecektir.

Bu tema ayarlarından bazılarını kullanarak bunu düzeltebilirsiniz,

+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"))

ve terazileri hizalayabilir,

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

böylece sonuçlar iyi görünecektir:

Bir örnek


3
bkz bu hizalama arsa panellerine daha güvenilir bir çözüm için
baptiste

Evet. Cevabım eski, @baptiste önerilen çözümü kullanın.
Lorinc Nyitrai

@LorincNyitrai Bu çizimi oluşturmak için lütfen kodunuzu paylaşabilir misiniz? Ayrıca ggplot2'de 2 grup için marjinal dağılım ile bir Hassas-Hatırlama dağılım grafiği yapmak istediğim bir durum var ama 2 grup için marjinal dağılım yapamıyorum. Teşekkürler
Newbie

@Yeni, bu cevap 3 yaşında, olabildiğince eski. Rdocumentation.org/packages/gtable/versions/0.2.0/topics/gtable veya benzeri bir şey kullanın .
Lorinc Nyitrai

29

BondedDust'un cevabında , marjinal dağılım göstergelerinin genel ruhu içinde çok küçük bir varyasyon .

Edward Tufte , bu halı alanlarının kullanımına 'nokta-çizgi çizimi' adını vermiştir ve VDQI'de her değişkenin aralığını belirtmek için eksen çizgilerini kullanma örneği vardır. Örneğimde, eksen etiketleri ve ızgara çizgileri de verilerin dağılımını göstermektedir. Etiketler, Tukey'in beş sayı özeti değerlerinde bulunur (minimum, alt menteşe, medyan, üst menteşe, maksimum) değerlerinde bulunur ve her bir değişkenin yayılımı hakkında hızlı bir izlenim verir.

Dolayısıyla bu beş sayı bir kutu grafiğinin sayısal bir temsilidir. Biraz zor çünkü düzensiz aralıklı ızgara çizgileri eksenlerin doğrusal olmayan bir ölçeğe sahip olduğunu gösteriyor (bu örnekte doğrusaldır). Belki de ızgara çizgilerini atlamak veya normal konumlarda olmaya zorlamak ve etiketlerin beş sayı özetini göstermesine izin vermek en iyisidir.

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))

resim açıklamasını buraya girin


12

Farklı grupları karşılaştırırken bu tür bir arsa için tatmin edici bir çözüm olmadığından, bunu yapmak için bir işlev yazdım .

Hem gruplandırılmış hem de gruplandırılmamış veriler için çalışır ve ek grafiksel parametreleri kabul eder:

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

resim açıklamasını buraya girin

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)

resim açıklamasını buraya girin


9

ggpubrBu sorun için çok iyi çalışıyor gibi görünen paketi ( ) buldum ve verileri görüntülemek için çeşitli olasılıkları göz önünde bulundurur.

Pakete bağlantı burada ve bu bağlantıda kullanmak için güzel bir öğretici bulacaksınız. Bütünlük için çoğalttığım örneklerden birini ekliyorum.

İlk olarak paketi kurdum (gerektirir devtools)

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

Farklı gruplar için farklı histogramların gösterilmesine ilişkin özel örnek için aşağıdakilerden bahseder ggExtra: "Bunun bir sınırlaması ggExtra, dağılım grafiğinde ve marjinal grafiklerde birden fazla grupla baş edememesidir. Aşağıdaki R kodunda, cowplotpaketi kullanarak çözüm . " Benim durumumda, ikinci paketi kurmak zorunda kaldım:

install.packages("cowplot")

Ve bu kod parçasını takip ettim:

# 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))

Hangi benim için iyi çalıştı:

İris marjinal histogramları dağılım grafiğini ayarla

resim açıklamasını buraya girin


Ortadaki arsa bir kare yapmak için ne yapmanız gerekir?
JAQuent

Demek istediğin noktaların şekli? Argüman eklemeyi deneyin shape = 19içinde ggscatter. Buradaki
Alf Pascu

7

Ggstatsplot kullanarak marjinal histogramlarla çekici dağılım grafikleri kolayca oluşturabilirsiniz (ayrıca bir modele uyacak ve tanımlayacaktır):

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
)

resim açıklamasını buraya girin

Veya biraz daha çekici (varsayılan olarak) 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)
)

resim açıklamasını buraya girin

GÜNCELLEME:

@Aickley tarafından önerildiği gibi arsa oluşturmak için gelişimsel sürümünü kullandım.


1
Y eksenindeki histogram yanlıştır, çünkü yalnızca x eksenindeki bir kopyadır. Bu yalnızca son zamanlarda github.com/kassambara/ggpubr/issues/85 düzeltildi .
aickley

7

Bu eski bir soru, ama son zamanlarda aynı problemle karşılaştığım için burada bir güncelleme yayınlamanın yararlı olacağını düşündüm (yardım için Stefanie Mueller'e teşekkürler!).

GridExtra kullanarak en çok oylanan cevap çalışıyor, ancak eksenlerde hizalama, yorumlarda belirtildiği gibi zor / hileli. Bu, ggExtra paketinden ggMarginal komutu kullanılarak şu şekilde çözülebilir:

#load packages
library(tidyverse) #for creating dummy dataset only
library(ggExtra)

#create dummy data
a = round(rnorm(1000,mean=10,sd=6),digits=0)
b = runif(1000,min=1.0,max=1.6)*a
b = b+runif(1000,min=9,max=15)

DummyData <- data.frame(var1 = b, var2 = a) %>% 
  filter(var1 > 0 & var2 > 0)

#plot
p = ggplot(DummyData, aes(var1, var2)) + geom_point(alpha=0.3)
ggMarginal(p, type = "histogram")

resim açıklamasını buraya girin


Sadece bunun orijinal ggExtra paket geliştiricisi tarafından başka bir cevapta gönderildiğini fark ettim. Yukarıda açıkladığım nedenle, bunun yerine kabul edilen cevabı yapmanızı tavsiye ederim!
Victoria Auyeung

6

Bu seçenekleri denedim, ancak sonuçlardan veya oraya ulaşmak için kullanmanız gereken dağınık koddan memnun kalmadım. Şanslıyım, Thomas Lin Pedersen sadece işi oldukça zarif bir şekilde yapan patchwork adlı bir paket geliştirdi .

Marjinal histogramlı bir dağılım grafiği oluşturmak istiyorsanız, önce bu üç grafiği ayrı ayrı oluşturmanız gerekir.

library(ggplot2)

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

plot1 <- ggplot(xy, aes(x = x, y = y)) + 
  geom_point() 

dens1 <- ggplot(xy, aes(x = x)) + 
  geom_histogram(color = "black", fill = "white") + 
  theme_void()

dens2 <- ggplot(xy, aes(x = y)) + 
  geom_histogram(color = "black", fill = "white") + 
  theme_void() + 
  coord_flip()

Yapılması gereken tek şey, bu grafikleri basit bir şekilde eklemek +ve düzeni fonksiyonla belirtmektir plot_layout().

library(patchwork)

dens1 + plot_spacer() + plot1 + dens2 + 
  plot_layout(
    ncol = 2, 
    nrow = 2, 
    widths = c(4, 1),
    heights = c(1, 4)
  ) 

İşlev plot_spacer()sağ üst köşeye boş bir grafik ekler. Diğer tüm argümanlar açıklayıcı olmalıdır.

resim açıklamasını buraya girin

Histogramlar büyük ölçüde seçilen bin genişliğe bağlı olduğu için, yoğunluk çizimlerini tercih ettiği söylenebilir. Bazı küçük değişikliklerle, örneğin göz izleme verileri için güzel bir arsa elde edilir.

library(ggpubr)

plot1 <- ggplot(df, aes(x = Density, y = Face_sum, color = Group)) + 
  geom_point(aes(color = Group), size = 3) + 
  geom_point(shape = 1, color = "black", size = 3) + 
  stat_smooth(method = "lm", fullrange = TRUE) +
  geom_rug() + 
  scale_y_continuous(name = "Number of fixated faces", 
                     limits = c(0, 205), expand = c(0, 0)) + 
  scale_x_continuous(name = "Population density (lg10)", 
                     limits = c(1, 4), expand = c(0, 0)) + 
  theme_pubr() +
  theme(legend.position = c(0.15, 0.9)) 

dens1 <- ggplot(df, aes(x = Density, fill = Group)) + 
  geom_density(alpha = 0.4) + 
  theme_void() + 
  theme(legend.position = "none")

dens2 <- ggplot(df, aes(x = Face_sum, fill = Group)) + 
  geom_density(alpha = 0.4) + 
  theme_void() + 
  theme(legend.position = "none") + 
  coord_flip()

dens1 + plot_spacer() + plot1 + dens2 + 
  plot_layout(ncol = 2, nrow = 2, widths = c(4, 1), heights = c(1, 4))

resim açıklamasını buraya girin

Veriler bu noktada sağlanmasa da, temel prensipler açık olmalıdır.


4

@ Alf-pascu'nun cevabı üzerine inşa etmek için, her bir komployu manuel olarak kurmak ve onları düzenlemek cowplot, hem ana hem de marjinal arsalara göre (diğer çözümlerin bazılarına kıyasla) çok fazla esneklik sağlar. Gruplara göre dağılımlar buna bir örnektir. Ana grafiğin 2D yoğunluk grafiğine değiştirilmesi başka bir şeydir.

Aşağıdakiler, marjinal histogramlarla (uygun şekilde hizalanmış) bir dağılım grafiği oluşturur.

library("ggplot2")
library("cowplot")

# Set up scatterplot
scatterplot <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
  geom_point(size = 3, alpha = 0.6) +
  guides(color = FALSE) +
  theme(plot.margin = margin())


# Define marginal histogram
marginal_distribution <- function(x, var, group) {
  ggplot(x, aes_string(x = var, fill = group)) +
    geom_histogram(bins = 30, alpha = 0.4, position = "identity") +
    # geom_density(alpha = 0.4, size = 0.1) +
    guides(fill = FALSE) +
    theme_void() +
    theme(plot.margin = margin())
}

# Set up marginal histograms
x_hist <- marginal_distribution(iris, "Sepal.Length", "Species")
y_hist <- marginal_distribution(iris, "Sepal.Width", "Species") +
  coord_flip()

# Align histograms with scatterplot
aligned_x_hist <- align_plots(x_hist, scatterplot, align = "v")[[1]]
aligned_y_hist <- align_plots(y_hist, scatterplot, align = "h")[[1]]

# Arrange plots
plot_grid(
  aligned_x_hist
  , NULL
  , scatterplot
  , aligned_y_hist
  , ncol = 2
  , nrow = 2
  , rel_heights = c(0.2, 1)
  , rel_widths = c(1, 0.2)
)

marjinal histogramlı dağılım grafiği

Bunun yerine bir 2B yoğunluk grafiğini çizmek için sadece ana grafiği değiştirin.

# Set up 2D-density plot
contour_plot <- ggplot(iris, aes(x = Sepal.Length, y = Sepal.Width, color = Species)) +
  stat_density_2d(aes(alpha = ..piece..)) +
  guides(color = FALSE, alpha = FALSE) +
  theme(plot.margin = margin())

# Arrange plots
plot_grid(
  aligned_x_hist
  , NULL
  , contour_plot
  , aligned_y_hist
  , ncol = 2
  , nrow = 2
  , rel_heights = c(0.2, 1)
  , rel_widths = c(1, 0.2)
)

resim açıklamasını buraya girin


3

Başka bir çözüm kullanarak ggpubrve cowplot, ama burada biz kullanarak araziler oluşturmak cowplot::axis_canvasve orijinal arsa ekleyebilirsiniz cowplot::insert_xaxis_grob:

library(cowplot) 
library(ggpubr)

# Create main plot
plot_main <- ggplot(faithful, aes(eruptions, waiting)) +
  geom_point()

# Create marginal plots
# Use geom_density/histogram for whatever you plotted on x/y axis 
plot_x <- axis_canvas(plot_main, axis = "x") +
  geom_density(aes(eruptions), faithful)
plot_y <- axis_canvas(plot_main, axis = "y", coord_flip = TRUE) +
  geom_density(aes(waiting), faithful) +
  coord_flip()

# Combine all plots into one
plot_final <- insert_xaxis_grob(plot_main, plot_x, position = "top")
plot_final <- insert_yaxis_grob(plot_final, plot_y, position = "right")
ggdraw(plot_final)

resim açıklamasını buraya girin


2

Günümüzde, dağılım grafiğini marjinal histogramlarıyla yapan en az bir CRAN paketi vardır.

library(psych)
scatterHist(rnorm(1000), runif(1000))

ScatterHist öğesinden örnek çizim


0

Etkileşimli formunu kullanabilir ve ggExtra::ggMarginalGadget(yourplot) kutu grafikleri, keman grafikleri, yoğunluk grafikleri ve histogramlar arasında kolayca seçim yapabilirsiniz.

bunun gibi

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.