Làm cách nào để chồng các ô mật độ trong R?


81

Tôi muốn chồng 2 ô mật độ trên cùng một thiết bị với R. Làm cách nào để làm điều đó? Tôi đã tìm kiếm trên web nhưng tôi không tìm thấy bất kỳ giải pháp rõ ràng nào.

Ý tưởng của tôi là đọc dữ liệu từ tệp văn bản (cột) và sau đó sử dụng

plot(density(MyData$Column1))
plot(density(MyData$Column2), add=T)

Hoặc một cái gì đó trong tinh thần này.

Câu trả lời:


92

sử dụng linescho cái thứ hai:

plot(density(MyData$Column1))
lines(density(MyData$Column2))

Tuy nhiên, hãy đảm bảo rằng các giới hạn của cốt truyện đầu tiên là phù hợp.


9
+1 Bạn có thể cần thứ gì đó phức tạp hơn một chút khi hai mật độ có phạm vi khác nhau và đường cong thứ hai không nằm trong giới hạn của âm mưu. Sau đó, bạn có thể tính toán mật độ trước khi vẽ biểu đồ và tính toán một cách thích hợp ylimbằng cách sử dụng các đối tượng chứa hai đối tượng ước lượng mật độ range(dens1$y, dens2$y)ở đâu dens1dens2là những đối tượng nào. Sử dụng điều này ylimtrong cuộc gọi đến plot().
Gavin Simpson

2
Bạn có thể cũng sẽ muốn phân biệt giữa hai dòng. Đặt độ rộng dòng ( lwd), loại dòng ( lty) hoặc màu dòng ( col) sẽ hữu ích ở đây. Vào thời điểm đó, bạn cũng có thể cân nhắc thêm một huyền thoại, sử dụnglegend()
nullglob

@Gavin Nếu OP đang đọc từ một tệp, tôi sẽ xây dựng một hàm phức tạp có thể đọc trong dữ liệu (sapply, lapply), tìm phạm vi của tất cả các tập dữ liệu, đặt phạm vi mặc định thành phạm vi tối đa của tất cả và sau đó vẽ đồ thị (dòng ) mật độ.
Roman Luštrik

50

ggplot2 là một gói đồ họa khác xử lý những thứ như vấn đề phạm vi mà Gavin đề cập theo cách khá khéo léo. Nó cũng xử lý tự động tạo ra các huyền thoại phù hợp và nhìn chung có cảm giác bóng bẩy hơn theo ý kiến ​​của tôi khi sử dụng ít thao tác thủ công hơn.

library(ggplot2)

#Sample data
dat <- data.frame(dens = c(rnorm(100), rnorm(100, 10, 5))
                   , lines = rep(c("a", "b"), each = 100))
#Plot.
ggplot(dat, aes(x = dens, fill = lines)) + geom_density(alpha = 0.5)

nhập mô tả hình ảnh ở đây


8
Nhu cầu data.frame của OP được nóng chảy mẫu dài đầu tiên:ggplot (melt (MyData), mapping = aes (fill = variable, x = value)) + geom_density (alpha = .5)
cbeleites không hài lòng với SX

1
Cốt truyện tốt đẹp. "Dat2" ... là gì? "tan chảy" (không tìm thấy lệnh) là gì?
Erik Aronesty,

@ErikAronesty - bạn đoán là tốt như tôi ở điểm này, tôi đã trả lời câu này hai năm trước! Tôi suy đoán rằng tôi đã có một đối tượng khác được đặt tên dattrong môi trường của mình nên đã đặt tên cho nó dat2... dữ liệu mô phỏng mà tôi cung cấp hoạt động như được quảng cáo. các melt()lệnh xuất phát từ gói reshape2. Trở lại năm 2011, reshape2được tự động tải khi ggplot2được tải, nhưng điều đó không còn xảy ra nữa nên bạn cần phải làm library(reshape2)riêng.
Đuổi theo

21

Thêm phiên bản đồ họa cơ sở quan tâm đến giới hạn trục y, thêm màu sắc và hoạt động cho bất kỳ số lượng cột nào:

Nếu chúng ta có tập dữ liệu:

myData <- data.frame(std.nromal=rnorm(1000, m=0, sd=1),
                     wide.normal=rnorm(1000, m=0, sd=2),
                     exponent=rexp(1000, rate=1),
                     uniform=runif(1000, min=-3, max=3)
                     )

Sau đó, để vẽ các mật độ:

dens <- apply(myData, 2, density)

plot(NA, xlim=range(sapply(dens, "[", "x")), ylim=range(sapply(dens, "[", "y")))
mapply(lines, dens, col=1:length(dens))

legend("topright", legend=names(dens), fill=1:length(dens))

Cái nào mang lại:

nhập mô tả hình ảnh ở đây


Tôi thích ví dụ này, nhưng nếu bạn có các cột dữ liệu bao gồm các giá trị NA thì nó không hoạt động. Tôi không chắc làm thế nào để sửa đổi mã, nhưng điều này sẽ hữu ích
daisy

1
@daisy thay đổi dòng này dens <- apply(myData, 2, density)thành dens <- apply(myData, 2, density, na.rm=TRUE)và nó sẽ hoạt động.
Karolis Koncevičius

12

Chỉ để cung cấp một bộ hoàn chỉnh, đây là phiên bản câu trả lời của Chase sử dụng lattice:

dat <- data.frame(dens = c(rnorm(100), rnorm(100, 10, 5))
                   , lines = rep(c("a", "b"), each = 100))

densityplot(~dens,data=dat,groups = lines,
            plot.points = FALSE, ref = TRUE, 
            auto.key = list(space = "right"))

tạo ra một âm mưu như thế này: nhập mô tả hình ảnh ở đây


Mà không cần tạo mới data.frame: densityplot(~rnorm(100)+rnorm(100, 10, 5), plot.points=FALSE, ref=TRUE, auto.key = list(space = "right")). Hoặc đối với dữ liệu OP densityplot(~Column1+Column2, data=myData).
Marek

6

Đó là cách tôi làm điều đó ở cơ sở (nó thực sự được đề cập trong các nhận xét câu trả lời đầu tiên nhưng tôi sẽ hiển thị mã đầy đủ ở đây, bao gồm cả chú giải vì tôi chưa thể bình luận ...)

Trước tiên, bạn cần lấy thông tin về các giá trị tối đa cho trục y từ các biểu đồ mật độ. Vì vậy, trước tiên bạn cần thực sự tính toán các mật độ riêng biệt

dta_A <- density(VarA, na.rm = TRUE)
dta_B <- density(VarB, na.rm = TRUE)

Sau đó, vẽ biểu đồ theo câu trả lời đầu tiên và xác định các giá trị tối thiểu và tối đa cho trục y mà bạn vừa nhận được. (Tôi đặt giá trị tối thiểu thành 0)

plot(dta_A, col = "blue", main = "2 densities on one plot"), 
     ylim = c(0, max(dta_A$y,dta_B$y)))  
lines(dta_B, col = "red")

Sau đó, thêm chú giải vào góc trên cùng bên phải

legend("topright", c("VarA","VarB"), lty = c(1,1), col = c("blue","red"))

3

Tôi đã lấy ví dụ về mạng tinh thể ở trên và tạo một hàm tiện lợi. Có lẽ có một cách tốt hơn để làm điều này với việc định hình lại thông qua tan / đúc. (Nhận xét hoặc chỉnh sửa nếu bạn thấy cải thiện.)

multi.density.plot=function(data,main=paste(names(data),collapse = ' vs '),...){
  ##combines multiple density plots together when given a list
  df=data.frame();
  for(n in names(data)){
    idf=data.frame(x=data[[n]],label=rep(n,length(data[[n]])))
    df=rbind(df,idf)
  }
  densityplot(~x,data=df,groups = label,plot.points = F, ref = T, auto.key = list(space = "right"),main=main,...)
}

Ví dụ sử dụng:

multi.density.plot(list(BN1=bn1$V1,BN2=bn2$V1),main='BN1 vs BN2')

multi.density.plot(list(BN1=bn1$V1,BN2=bn2$V1))

2

Bạn có thể sử dụng ggjoygói. Giả sử rằng chúng ta có ba bản betaphân phối khác nhau như:

set.seed(5)
b1<-data.frame(Variant= "Variant 1", Values = rbeta(1000, 101, 1001))
b2<-data.frame(Variant= "Variant 2", Values = rbeta(1000, 111, 1011))
b3<-data.frame(Variant= "Variant 3", Values = rbeta(1000, 11, 101))


df<-rbind(b1,b2,b3)

Bạn có thể nhận được ba bản phân phối khác nhau như sau:

library(tidyverse)
library(ggjoy)


ggplot(df, aes(x=Values, y=Variant))+
    geom_joy(scale = 2, alpha=0.5) +
    scale_y_discrete(expand=c(0.01, 0)) +
    scale_x_continuous(expand=c(0.01, 0)) +
    theme_joy()

nhập mô tả hình ảnh ở đây


2

Bất cứ khi nào có vấn đề về giới hạn trục không khớp, công cụ thích hợp trong baseđồ họa là sử dụng matplot. Điều quan trọng là tận dụng các đối số fromvà . Có một chút khó khăn, nhưng khá đơn giản để tự mình lăn xả:todensity.default

set.seed(102349)
x1 = rnorm(1000, mean = 5, sd = 3)
x2 = rnorm(5000, mean = 2, sd = 8)

xrng = range(x1, x2)

#force the x values at which density is
#  evaluated to be the same between 'density'
#  calls by specifying 'from' and 'to'
#  (and possibly 'n', if you'd like)
kde1 = density(x1, from = xrng[1L], to = xrng[2L])
kde2 = density(x2, from = xrng[1L], to = xrng[2L])

matplot(kde1$x, cbind(kde1$y, kde2$y))

Một âm mưu mô tả đầu ra của lệnh gọi tới matplot.  Hai đường cong được quan sát, một màu đỏ, một màu đen;  đường cong màu đen mở rộng cao hơn màu đỏ, trong khi đường cong màu đỏ là "béo hơn".

Thêm chuông và còi như mong muốn ( matplotchấp nhận tất cả tiêu chuẩn plot/ parlập luận, ví dụ như lty, type, col, lwd, ...).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.