2015-07-01 15 views
7

Tôi có các ô phân tán dữ liệu 2D từ hai danh mục. Tôi muốn thêm các đường mật độ cho mỗi chiều - không phải bên ngoài cốt truyện (xem Scatterplot with marginal histograms in ggplot2) mà phải trên bề mặt âm mưu. Tôi có thể có được điều này cho kích thước trục x, như thế này:ggplot2: thêm đường cong mật độ có điều kiện mô tả cả hai kích thước của phân tán

set.seed(123) 
dim1 <- c(rnorm(100, mean=1), rnorm(100, mean=4)) 
dim2 <- rnorm(200, mean=1) 
cat <- factor(c(rep("a", 100), rep("b", 100))) 
mydf <- data.frame(cbind(dim2, dim1, cat)) 
ggplot(data=mydf, aes(x=dim1, y=dim2, colour=as.factor(cat))) + 
    geom_point() + 
    stat_density(aes(x=dim1, y=(-2+(..scaled..))), 
    position="identity", geom="line") 

Nó trông như thế này:

enter image description here

Nhưng tôi muốn một cặp tương tự của đường cong mật độ chạy theo chiều dọc, cho thấy sự phân bố các điểm trong thứ nguyên y. Tôi đã thử

stat_density(aes(y=dim2, x=0+(..scaled..))), position="identity", geom="line) 

nhưng nhận được lỗi "tỷ lệ yêu cầu thiếu tính thẩm mỹ sau: x".

Bất kỳ ý tưởng nào? nhờ

+1

tôi đã thêm (xem xét cấp phát) âm mưu của mình. Điều này trông giống như một khó khăn. Tôi tự hỏi nếu 'coord_flip' hữu ích ở đây – C8H10N4O2

+1

Điều này thật thú vị, mặc dù nó không phải là những gì bạn đang tìm kiếm:' ggplot (dữ liệu = mydf, aes (x = dim1, y = dim2, màu = as.factor (cat))) + stat_density2d() ' – C8H10N4O2

Trả lời

8

Bạn có thể nhận được mật độ của các biến số dim2. Sau đó, lật các trục và lưu trữ chúng trong một data.frame mới. Sau đó nó chỉ đơn giản là vẽ chúng trên đầu trang của đồ thị khác.

p <- ggplot(data=mydf, aes(x=dim1, y=dim2, colour=as.factor(cat))) + 
    geom_point() + 
    stat_density(aes(x=dim1, y=(-2+(..scaled..))), 
       position="identity", geom="line") 

stuff <- ggplot_build(p) 
xrange <- stuff[[2]]$ranges[[1]]$x.range # extract the x range, to make the new densities align with y-axis 

## Get densities of dim2 
ds <- do.call(rbind, lapply(unique(mydf$cat), function(lev) { 
    dens <- with(mydf, density(dim2[cat==lev])) 
    data.frame(x=dens$y+xrange[1], y=dens$x, cat=lev) 
})) 

p + geom_path(data=ds, aes(x=x, y=y, color=factor(cat))) 

enter image description here

+1

Giải pháp rất đẹp. Kicking bản thân mình vì không sử dụng 'density' – C8H10N4O2

+0

cảm ơn, có vẻ như ggplot có thể mở rộng các giá trị y của mật độ một chút? Đường cong của bạn sau khi coord_flip trông hơi "cao" hơn. – jenesaisquoi

+0

Nếu tập dữ liệu ban đầu có một yếu tố (4 chiều, giả sử) mà tôi đã sử dụng để facet_grid, bất kỳ suy nghĩ về cách sửa đổi mật độ khai thác do.call để kéo dữ liệu đó ra? –

2

Cho đến nay tôi có thể sản xuất:

distrib_horiz <- stat_density(aes(x=dim1, y=(-2+(..scaled..))), 
           position="identity", geom="line") 

ggplot(data=mydf, aes(x=dim1, y=dim2, colour=as.factor(cat))) + 
    geom_point() + distrib_horiz 

enter image description here

Và:

distrib_vert <- stat_density(data=mydf, aes(x=dim2, y=(-2+(..scaled..))), 
          position="identity", geom="line") 

ggplot(data=mydf, aes(x=dim2, y=dim1, colour=as.factor(cat))) + 
    geom_point() + distrib_vert + coord_flip() 

enter image description here

Nhưng kết hợp chúng được chứng minh khéo léo.

+0

giữ lại tỷ lệ phần trăm trong cấu trúc dữ liệu có vẻ như là một khởi đầu tốt đẹp (nếu có thể vẽ một đường từ nó, ggplot sẽ không phải biết vị trí của x, y đến từ đâu). Nhưng tôi không chắc chắn làm thế nào để truy cập dữ liệu mật độ. –

1

Cho đến nay tôi chỉ có một giải pháp từng phần vì tôi không quản lý để có được đường thẳng đứng stat_density cho từng danh mục riêng lẻ, chỉ cho tổng bộ. Có lẽ điều này vẫn có thể giúp đỡ như là một điểm khởi đầu cho việc tìm kiếm một giải pháp tốt hơn. Đề xuất của tôi là thử với hàm ggMarginal() từ gói ggExtra.

p <- ggplot(data=mydf, aes(x=dim1, y=dim2, colour=as.factor(cat))) + 
    geom_point() + stat_density(aes(x=dim1, y=(-2+(..scaled..))), 
      position="identity", geom="line") 
library(ggExtra) 
ggMarginal(p,type = "density", margins = "y", size = 4) 

Đây là những gì tôi có được: enter image description here

Tôi biết nó không phải là hoàn hảo, nhưng có lẽ đó là một bước theo hướng hữu ích. Ít nhất tôi hy vọng như vậy. Nhìn về phía trước để nhìn thấy câu trả lời khác.

Các vấn đề liên quan