Làm cách nào để vẽ biểu đồ phễu bằng ggplot2 trong R?


12

Như tiêu đề, tôi cần vẽ một cái gì đó như thế này:

văn bản thay thế

Ggplot, hoặc các gói khác nếu ggplot không có khả năng, có thể được sử dụng để vẽ một cái gì đó như thế này không?


2
Tôi đã có một vài ý tưởng về cách thực hiện và thực hiện điều này, nhưng sẽ đánh giá cao việc có một số dữ liệu để chơi. Bất cứ ý tưởng về điều đó?
Đuổi theo

1
Có, ggplot có thể dễ dàng vẽ một cốt truyện được tạo thành từ các điểm và đường thẳng;) geom_smooth sẽ giúp bạn đạt 95% - nếu bạn muốn có thêm lời khuyên, bạn sẽ cần cung cấp thêm chi tiết.
hadley

2
Đây không phải là một âm mưu kênh. Thay vào đó, các dòng rõ ràng được xây dựng từ các ước tính về lỗi tiêu chuẩn dựa trên số lượng tuyển sinh. Chúng dường như có ý định kèm theo một tỷ lệ dữ liệu xác định , điều này sẽ khiến chúng bị giới hạn dung sai. Chúng có khả năng có dạng y = đường cơ sở + hằng số / Sqrt (# nhập học * f (đường cơ sở)). Bạn có thể sửa đổi mã trong các phản hồi hiện có để vẽ biểu đồ các dòng, nhưng bạn có thể sẽ cần cung cấp công thức của riêng mình để tính toán chúng: các ví dụ tôi đã thấy các khoảng tin cậy của biểu đồ cho chính dòng được trang bị . Đó là lý do tại sao chúng trông rất khác nhau.
whuber

@whuber (+1) Đó thực sự là một điểm rất tốt. Tôi hy vọng điều này có thể cung cấp một điểm khởi đầu tốt dù sao (ngay cả khi mã R của tôi không được tối ưu hóa).
chl

Ggplot vẫn cung cấp stat_quantile()để đưa các lượng tử có điều kiện vào một biểu đồ phân tán. Sau đó, bạn có thể điều khiển dạng chức năng của hồi quy lượng tử với tham số công thức. Tôi muốn đề xuất những thứ như công thức = y~ns(x,4)để có được sự phù hợp mịn màng.
Shea Parkes

Câu trả lời:


12

Mặc dù vẫn còn chỗ để cải thiện, đây là một nỗ lực nhỏ với dữ liệu mô phỏng (không đồng nhất):

library(ggplot2)
set.seed(101)
x <- runif(100, min=1, max=10)
y <- rnorm(length(x), mean=5, sd=0.1*x)
df <- data.frame(x=x*70, y=y)
m <- lm(y ~ x, data=df) 
fit95 <- predict(m, interval="conf", level=.95)
fit99 <- predict(m, interval="conf", level=.999)
df <- cbind.data.frame(df, 
                       lwr95=fit95[,"lwr"],  upr95=fit95[,"upr"],     
                       lwr99=fit99[,"lwr"],  upr99=fit99[,"upr"])

p <- ggplot(df, aes(x, y)) 
p + geom_point() + 
    geom_smooth(method="lm", colour="black", lwd=1.1, se=FALSE) + 
    geom_line(aes(y = upr95), color="black", linetype=2) + 
    geom_line(aes(y = lwr95), color="black", linetype=2) +
    geom_line(aes(y = upr99), color="red", linetype=3) + 
    geom_line(aes(y = lwr99), color="red", linetype=3)  + 
    annotate("text", 100, 6.5, label="95% limit", colour="black", 
             size=3, hjust=0) +
    annotate("text", 100, 6.4, label="99.9% limit", colour="red", 
             size=3, hjust=0) +
    labs(x="No. admissions...", y="Percentage of patients...") +    
    theme_bw() 

văn bản thay thế


20

Nếu bạn đang tìm kiếm loại biểu đồ kênh (phân tích tổng hợp) này , thì đây có thể là điểm bắt đầu:

library(ggplot2)

set.seed(1)
p <- runif(100)
number <- sample(1:1000, 100, replace = TRUE)
p.se <- sqrt((p*(1-p)) / (number))
df <- data.frame(p, number, p.se)

## common effect (fixed effect model)
p.fem <- weighted.mean(p, 1/p.se^2)

## lower and upper limits for 95% and 99.9% CI, based on FEM estimator
number.seq <- seq(0.001, max(number), 0.1)
number.ll95 <- p.fem - 1.96 * sqrt((p.fem*(1-p.fem)) / (number.seq)) 
number.ul95 <- p.fem + 1.96 * sqrt((p.fem*(1-p.fem)) / (number.seq)) 
number.ll999 <- p.fem - 3.29 * sqrt((p.fem*(1-p.fem)) / (number.seq)) 
number.ul999 <- p.fem + 3.29 * sqrt((p.fem*(1-p.fem)) / (number.seq)) 
dfCI <- data.frame(number.ll95, number.ul95, number.ll999, number.ul999, number.seq, p.fem)

## draw plot
fp <- ggplot(aes(x = number, y = p), data = df) +
    geom_point(shape = 1) +
    geom_line(aes(x = number.seq, y = number.ll95), data = dfCI) +
    geom_line(aes(x = number.seq, y = number.ul95), data = dfCI) +
    geom_line(aes(x = number.seq, y = number.ll999), linetype = "dashed", data = dfCI) +
    geom_line(aes(x = number.seq, y = number.ul999), linetype = "dashed", data = dfCI) +
    geom_hline(aes(yintercept = p.fem), data = dfCI) +
    scale_y_continuous(limits = c(0,1.1)) +
  xlab("number") + ylab("p") + theme_bw() 
fp

văn bản thay thế


1
Sự hiện diện của linetype=2đối số bên trong aes()dấu ngoặc - vẽ các dòng 99% - dẫn đến lỗi "biến liên tục không thể được ánh xạ thành linetype" với ggplot2 hiện tại (0.9.3.1). Sửa đổi geom_line(aes(x = number.seq, y = number.ll999, linetype = 2), data = dfCI)để geom_line(aes(x = number.seq, y = number.ll999), linetype = 2, data = dfCI)làm việc cho tôi. Hãy sửa đổi câu trả lời ban đầu và mất điều này.


2

Mã của Bernd Weiss rất hữu ích. Tôi đã thực hiện một số sửa đổi dưới đây, để thay đổi / thêm một vài tính năng:

  1. Đã sử dụng sai số chuẩn làm thước đo độ chính xác, điển hình hơn cho các sơ đồ phễu mà tôi thấy (trong tâm lý học)
  2. Hoán đổi các trục, do đó độ chính xác (lỗi tiêu chuẩn) nằm trên trục y và kích thước hiệu ứng nằm trên trục x
  3. Được sử dụng geom_segmentthay geom_linecho đường phân định trung bình siêu phân tích, do đó, nó sẽ có cùng chiều cao với các đường phân định vùng tin cậy 95% và 99%
  4. Thay vì vẽ trung bình phân tích tổng hợp, tôi đã vẽ khoảng tin cậy 95%

Mã của tôi sử dụng trung bình phân tích tổng hợp là 0,0892 (se = 0,0035) làm ví dụ, nhưng bạn có thể thay thế các giá trị của riêng bạn.

estimate = 0.0892
se = 0.0035

#Store a vector of values that spans the range from 0
#to the max value of impression (standard error) in your dataset.
#Make the increment (the final value) small enough (I choose 0.001)
#to ensure your whole range of data is captured
se.seq=seq(0, max(dat$corr_zi_se), 0.001)

#Compute vectors of the lower-limit and upper limit values for
#the 95% CI region
ll95 = estimate-(1.96*se.seq)
ul95 = estimate+(1.96*se.seq)

#Do this for a 99% CI region too
ll99 = estimate-(3.29*se.seq)
ul99 = estimate+(3.29*se.seq)

#And finally, calculate the confidence interval for your meta-analytic estimate 
meanll95 = estimate-(1.96*se)
meanul95 = estimate+(1.96*se)

#Put all calculated values into one data frame
#You might get a warning about '...row names were found from a short variable...' 
#You can ignore it.
dfCI = data.frame(ll95, ul95, ll99, ul99, se.seq, estimate, meanll95, meanul95)


#Draw Plot
fp = ggplot(aes(x = se, y = Zr), data = dat) +
  geom_point(shape = 1) +
  xlab('Standard Error') + ylab('Zr')+
  geom_line(aes(x = se.seq, y = ll95), linetype = 'dotted', data = dfCI) +
  geom_line(aes(x = se.seq, y = ul95), linetype = 'dotted', data = dfCI) +
  geom_line(aes(x = se.seq, y = ll99), linetype = 'dashed', data = dfCI) +
  geom_line(aes(x = se.seq, y = ul99), linetype = 'dashed', data = dfCI) +
  geom_segment(aes(x = min(se.seq), y = meanll95, xend = max(se.seq), yend = meanll95), linetype='dotted', data=dfCI) +
  geom_segment(aes(x = min(se.seq), y = meanul95, xend = max(se.seq), yend = meanul95), linetype='dotted', data=dfCI) +
  scale_x_reverse()+
  scale_y_continuous(breaks=seq(-1.25,2,0.25))+
  coord_flip()+
  theme_bw()
fp

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

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.