ggplot2에서 한계 히스토그램이있는 산점도


137

아래 샘플과 같이 한계 히스토그램으로 산점도를 만드는 방법이 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()

여기에 게시 된 기능으로 정렬 하십시오 . 그러나 간단히 이야기하자면 :이 그래프를 만드는 방법이 있습니까?


@DWin은 고맙습니다. 그러나 나는 그것이 내 질문에 준 해결책이라고 생각합니다. 그러나, 나는 geom_rag ()가 아래에 당신에게 많은 것을 준다고 생각합니다!
Seb

1
같은 주제를 다루는 최근 블로그 게시물에서 : blog.mckuhn.de/2009/09/learning-ggplot2-2d-plot-with.html 도 꽤 좋아 보입니다 :)
Seb

그래픽 갤러리의 새로운 웹 사이트는 다음과 같습니다. gallery.r-enthusiasts.com
IRTFM

@Seb 당신은 "합의 된 답변"을 ggExtra 패키지에 대한 것으로 변경하는 것을 고려할 수 있습니다.
DeanAttali

답변:


93

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 함수를 사용하십시오.

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

음모


6
1+는 배치를 보여 주지만, 내부 분산이 한계 히스토그램과 "일렬로"정렬되도록하려면 무작위 샘플링을 다시 수행하지 않아야합니다.
IRTFM

1
네가 옳아. 동일한 분포에서 샘플링되므로 한계 히스토그램은 이론적으로 산점도와 일치해야합니다.
oeo4b

8
"이론"에서 그들은 무의식적으로 "일치"할 것이다. 실제로 일치하는 횟수는 무한정 작습니다. 그것은 제공된 예를 사용하는 것은 매우 간단 xy <- data.frame(x=rnorm(300), y=rt(300,df=2) )하고 사용을 data=xyggplot 통화에서.
IRTFM

7
플롯 축이 일반적으로 정확하게 정렬되지 않으므로이 솔루션을 권장하지 않습니다. 다행스럽게도 ggplot2의 향후 버전에서는 축을보다 쉽게 ​​정렬하거나 플롯 패널의 측면에 맞춤 주석 (예 : 격자의 사용자 정의 보조 축 함수)을 허용 할 수 있습니다.
baptiste

9
아니요, 일반적으로는 그렇지 않습니다. ggplot2는 현재 축 레이블의 범위 등에 따라 변하는 다양한 패널 너비를 출력합니다. ggExtra :: align.plots에서 현재 축을 정렬하는 데 필요한 해킹 종류를 확인하십시오.
baptiste

115

이것은 완전히 반응하는 대답은 아니지만 매우 간단합니다. 주변 밀도를 표시하는 대체 방법과 투명도를 지원하는 그래픽 출력에 알파 수준을 사용하는 방법을 보여줍니다.

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

여기에 이미지 설명을 입력하십시오


5
밀도를 보여주는 흥미로운 방법입니다. 이 답변을 추가해 주셔서 감사합니다. :)
Michelle

21
이 방법은 한계 히스토그램을 넣는 것보다 훨씬 흔합니다. 실제로, 한계 히스토그램이 포함 된 게시 된 기사를 본 적이없는 게시 된 기사에서는 양탄자 표시가 일반적입니다.
Xu Wang

매우 흥미롭고 직관적 인 대안 답변! 그리고 매우 간단합니다! 정답보다 더 많은 표를 얻는 것도 당연합니다. 내 이해는 이것이 본질적으로 1 차원 히트 맵이라는 것입니다 . 깔개는 붐비는 곳이면 더 어둡습니다. 내 유일한 걱정은 히트 맵의 해상도가 히스토그램만큼 높지 않다는 것입니다. 예. 줄거리가 작 으면 모든 깔개가 함께 압착되어 분포를 감지하기 어렵습니다. 히스토그램에는 한계가 없습니다. 아이디어 주셔서 감사합니다!
HongboZhu

94

약간 늦을 수도 있지만 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")

여기에 이미지 설명을 입력하십시오


1
패키지 주셔서 감사합니다. 상자 밖으로 작동합니다!
heroxbd

이 패키지를 사용하여 색상별로 그룹화 된 객체에 대해 한계 밀도 플롯을 그릴 수 있습니까?
GegznaV

아니요, 그런 논리는 없습니다
DeanAttali

1
@jjrr 작동하지 않는 문제와 어떤 문제가 있는지 잘 모르겠지만 노트북에서 렌더링하는 방법에 대한 github의 최근 문제가 있으며 해결책도 있습니다. github.com/daattali/ ggExtra / issues / 89
DeanAttali

1
@GegznaV, 여백 밀도 플롯을 색상별로 그룹화하는 방법을 찾고 있다면 ggExtra 0.9 : ggMarginal (p, type = "density", size = 5, groupColour = TRUE)
MartineJ

46

한 번의 추가로, 우리 이후에 이것을하는 사람들의 검색 시간을 절약하기 위해서입니다.

범례, 축 레이블, 축 텍스트, 눈금은 플롯이 서로 멀어 지도록하기 때문에 플롯이보기 흉하고 일관성이없는 것처럼 보입니다.

이러한 테마 설정 중 일부를 사용하여이 문제를 해결할 수 있습니다.

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

결과가 좋아 보일 것입니다.

예


3
플롯 패널을 정렬하는보다 안정적인 솔루션을 보려면 이것을 보십시오
baptiste

예. 내 답변이 구식입니다. @baptiste가 제안한 솔루션을 사용하십시오.
Lorinc Nyitrai

@LorincNyitrai이 음모를 생성하기 위해 코드를 공유 할 수 있습니까? 또한 2 그룹에 대한 한계 분포를 사용하여 ggplot2에서 Precision-Recall 산포도를 만들고 싶지만 2 그룹에 대해 한계 분포를 수행 할 수없는 조건이 있습니다. 감사합니다
Newbie

@Newbie,이 답변은 가능한 오래된 것입니다. rdocumentation.org/packages/gtable/versions/0.2.0/topics/gtable 또는 이와 유사한 것을 사용하십시오 .
Lorinc Nyitrai

29

한계 분포 지표의 일반적인 정신에서 BondedDust의 답변 에 대한 아주 작은 변형 .

Edward Tufte 는이 러그 플롯 사용을 '점-대시 플롯'이라고하며 VDQI에서 축선을 사용하여 각 변수의 범위를 나타내는 예를 보여줍니다. 이 예에서 축 레이블과 그리드 선은 데이터 분포를 나타냅니다. 레이블은 Tukey의 5 개 숫자 요약 (최소, 힌지, 중간, 힌지, 최대) 값에 위치하여 각 변수의 확산을 신속하게 보여줍니다.

따라서이 5 개의 숫자는 상자 그림의 숫자 표현입니다. 간격이 고르지 않은 그리드 선은 축에 비선형 스케일이 있음을 제안하기 때문에 약간 까다 롭습니다 (이 예에서는 선형 임). 그리드 선을 생략하거나 규칙적인 위치에 두도록하고 레이블에 5 개의 숫자 요약을 표시하는 것이 가장 좋습니다.

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

여기에 이미지 설명을 입력하십시오


12

다른 그룹을 비교할 때 이런 종류의 음모에 대한 만족스러운 해결책이 없었 으므로이 작업을 수행 하는 기능 을 작성했습니다 .

그룹화 된 데이터와 그룹화되지 않은 데이터 모두에 대해 작동하며 추가 그래픽 매개 변수를 허용합니다.

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)

여기에 이미지 설명을 입력하십시오


9

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

어느 것이 나를 위해 잘 작동했습니다 :

아이리스 세트 한계 히스토그램 산점도

여기에 이미지 설명을 입력하십시오


중간에 음모를 꾸미려면 어떻게해야합니까?
JAQuent

당신이 의미하는 점의 모양? 에 인수 shape = 19를 추가해보십시오 ggscatter. 모양에 대한 코드는 여기
Alf Pascu

7

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가 제안한대로 개발 버전을 사용하여 줄거리를 만들었습니다.


1
y 축의 막대 그래프는 x 축의 막대 그래프이므로 잘못된 것입니다. 이것은 최근에 github.com/kassambara/ggpubr/issues/85 에서만 수정되었습니다 .
aickley

7

이것은 오래된 질문이지만 최근 에이 같은 문제가 발생했기 때문에 여기에 업데이트를 게시하는 것이 도움이 될 것이라고 생각했습니다 (Stefanie Mueller에게 도움을 주셔서 감사합니다!).

gridExtra를 사용하여 가장 많이 답한 대답은 효과가 있지만 주석에서 지적했듯이 축을 정렬하는 것은 어렵습니다. 이제 ggExtra 패키지에서 ggMarginal 명령을 사용하여이를 해결할 수 있습니다.

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

여기에 이미지 설명을 입력하십시오


이것은 원래 ggExtra 패키지 개발자가 다른 답변으로 게시 한 것을 깨달았습니다. 위에서 설명한 이유로 대신 수락 된 답변을 작성하는 것이 좋습니다!
Victoria Auyeung

6

나는 그 옵션을 시도했지만 결과 또는 거기에 도착하기 위해 사용해야하는 지저분한 코드에 만족하지 않았습니다. 운 좋게도 Thomas Lin Pedersen은 patchwork 라는 패키지를 개발했습니다.이 패키지 는 꽤 우아한 방식으로 작업을 수행합니다.

한계 히스토그램으로 산점도를 생성하려면 먼저 세 개의 플롯을 별도로 생성해야합니다.

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

남은 것은 간단하게 플롯을 추가 +하고 함수를 사용하여 레이아웃을 지정하는 것 plot_layout()입니다.

library(patchwork)

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

이 함수 plot_spacer()는 오른쪽 상단에 빈 플롯을 추가합니다. 다른 모든 주장은 설명이 필요합니다.

여기에 이미지 설명을 입력하십시오

히스토그램은 선택된 바이너리 폭에 크게 의존하기 때문에 밀도 플롯을 선호한다고 주장 할 수 있습니다. 약간의 수정으로 예를 들어 시선 추적 데이터에 대한 아름다운 음모를 얻을 수 있습니다.

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

여기에 이미지 설명을 입력하십시오

이 시점에서 데이터는 제공되지 않지만 기본 원칙은 명확해야합니다.


4

@ alf-pascu의 답변을 바탕으로 각 플롯을 수동으로 설정하고 배치 cowplot하면 기본 및 한계 플롯 (다른 솔루션과 비교)에 대해 많은 유연성이 부여됩니다. 그룹 별 분포가 한 예입니다. 메인 플롯을 2D 밀도 플롯으로 변경하는 것도 또 다른 방법입니다.

다음은 (적절하게 정렬 된) 한계 히스토그램으로 산점도를 만듭니다.

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

한계 히스토그램이있는 산점도

대신 2D 밀도 플롯을 플롯하려면 주 플롯을 변경하십시오.

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

여기에 이미지 설명을 입력하십시오


3

ggpubrand를 사용하는 또 다른 솔루션 cowplot이지만 여기서는를 사용하여 플롯을 만들고 다음을 사용하여 cowplot::axis_canvas원래 플롯에 추가합니다 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)

여기에 이미지 설명을 입력하십시오


2

요즘에는 한계 히스토그램으로 산점도를 만드는 하나 이상의 CRAN 패키지가 있습니다.

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

scatterHist의 샘플 플롯


0

대화 형 형식을 사용하고 ggExtra::ggMarginalGadget(yourplot) 상자 그림, 바이올린 그림, 밀도 그림 및 히스토그램 중에서 쉽게 선택할 수 있습니다.

그렇게

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.