Đặt giới hạn trục riêng lẻ với facet_wrap and scale = “free” trong ggplot2


116

Tôi đang tạo một biểu đồ khía cạnh để xem các giá trị được dự đoán so với thực tế song song với một biểu đồ của giá trị dự đoán so với phần còn lại. Tôi sẽ sử dụng shinyđể giúp khám phá kết quả của nỗ lực lập mô hình bằng cách sử dụng các thông số đào tạo khác nhau. Tôi đào tạo mô hình với 85% dữ liệu, kiểm tra 15% còn lại và lặp lại điều này 5 lần, thu thập các giá trị thực tế / dự đoán mỗi lần. Sau khi tính toán các phần còn lại, của tôi data.frametrông như thế này:

head(results)
       act     pred       resid
2 52.81000 52.86750 -0.05750133
3 44.46000 42.76825  1.69175252
4 54.58667 49.00482  5.58184181
5 36.23333 35.52386  0.70947731
6 53.22667 48.79429  4.43237981
7 41.72333 41.57504  0.14829173

Những gì tôi muốn:

  • Cốt truyện cạnh nhau của predvs. actpredvs.resid
  • Phạm vi / giới hạn x / y predso với actgiống nhau, lý tưởng là từ min(min(results$act), min(results$pred))đếnmax(max(results$act), max(results$pred))
  • Phạm vi / giới hạn x / y cho predso với resid không bị ảnh hưởng bởi những gì tôi làm với âm mưu thực tế so với dự đoán. Vẽ đồ thị chỉ cho xhơn các giá trị dự đoán và ychỉ trên phạm vi dư là tốt.

Để xem cả hai mảnh đất cạnh nhau, tôi làm tan dữ liệu:

library(reshape2)
plot <- melt(results, id.vars = "pred")

Bây giờ âm mưu:

library(ggplot2)
p <- ggplot(plot, aes(x = pred, y = value)) + geom_point(size = 2.5) + theme_bw()
p <- p + facet_wrap(~variable, scales = "free")

print(p)

Điều đó khá gần với những gì tôi muốn:

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

Những gì tôi muốn là cho các phạm vi x và y cho thực tế so với dự đoán là giống nhau, nhưng tôi không chắc làm thế nào để xác định điều đó và tôi không cần thực hiện điều đó cho lô dự đoán so với phần còn lại vì phạm vi hoàn toàn khác nhau.

Tôi đã thử thêm một cái gì đó như thế này cho cả hai scale_x_continousscale_y_continuous:

min_xy <- min(min(plot$pred), min(plot$value))
max_xy <- max(max(plot$pred), max(plot$value))

p <- ggplot(plot, aes(x = pred, y = value)) + geom_point(size = 2.5) + theme_bw()
p <- p + facet_wrap(~variable, scales = "free")
p <- p + scale_x_continuous(limits = c(min_xy, max_xy))
p <- p + scale_y_continuous(limits = c(min_xy, max_xy))

print(p)

Nhưng điều đó chọn ra các min()giá trị còn lại.

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

Một ý tưởng cuối cùng tôi có là lưu trữ giá trị của giá trị tối thiểu actpredcác biến trước khi tan chảy, sau đó thêm chúng vào khung dữ liệu đã tan chảy để xác định chúng xuất hiện ở khía cạnh nào:

head(results)
       act     pred       resid
2 52.81000 52.86750 -0.05750133
3 44.46000 42.76825  1.69175252
4 54.58667 49.00482  5.58184181
5 36.23333 35.52386  0.70947731

min_xy <- min(min(results$act), min(results$pred))
max_xy <- max(max(results$act), max(results$pred))

plot <- melt(results, id.vars = "pred")

plot <- rbind(plot, data.frame(pred = c(min_xy, max_xy),
  variable = c("act", "act"), value = c(max_xy, min_xy)))

p <- ggplot(plot, aes(x = pred, y = value)) + geom_point(size = 2.5) + theme_bw()
p <- p + facet_wrap(~variable, scales = "free")

print(p)

Điều đó làm những gì tôi muốn, ngoại trừ các điểm cũng hiển thị:

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

Bất kỳ đề xuất để làm một cái gì đó như thế này?


Tôi đã thấy ý tưởng này để thêm vào geom_blank(), nhưng tôi không chắc chắn làm thế nào để chỉ định aes()bit và làm cho nó hoạt động bình thường hoặc geom_point()tương đương với việc sử dụng biểu đồ aes(y = max(..count..)).


Đây là dữ liệu để sử dụng (giá trị thực tế, dự đoán và giá trị còn lại của tôi trước khi tan chảy):

> dput(results)
structure(list(act = c(52.81, 44.46, 54.5866666666667, 36.2333333333333, 
53.2266666666667, 41.7233333333333, 35.2966666666667, 30.6833333333333, 
39.25, 35.8866666666667, 25.1, 29.0466666666667, 23.2766666666667, 
56.3866666666667, 42.92, 41.57, 27.92, 23.16, 38.0166666666667, 
61.8966666666667, 37.41, 41.6333333333333, 35.9466666666667, 
48.9933333333333, 30.5666666666667, 32.08, 40.3633333333333, 
53.2266666666667, 64.6066666666667, 38.5366666666667, 41.7233333333333, 
25.78, 33.4066666666667, 27.8033333333333, 39.3266666666667, 
48.9933333333333, 25.2433333333333, 32.67, 55.17, 42.92, 54.5866666666667, 
23.16, 64.6066666666667, 40.7966666666667, 39.0166666666667, 
41.6333333333333, 35.8866666666667, 25.1, 23.2766666666667, 44.46, 
34.2166666666667, 40.8033333333333, 24.5766666666667, 35.73, 
61.8966666666667, 62.1833333333333, 74.6466666666667, 39.4366666666667, 
36.6, 27.1333333333333), pred = c(52.8675013282404, 42.7682474758679, 
49.0048248585123, 35.5238560262515, 48.7942868566949, 41.5750416040131, 
33.9548164913007, 29.9787449128663, 37.6443975781139, 36.7196211666685, 
27.6043278172077, 27.0615724310721, 31.2073056885252, 55.0886903524179, 
43.0895814712768, 43.0895814712768, 32.3549865881578, 26.2428426737583, 
36.6926037128343, 56.7987490221996, 45.0370788180147, 41.8231642271826, 
38.3297859332601, 49.5343916620086, 30.8535641206809, 29.0117492750411, 
36.9767968381391, 49.0826677983065, 54.4678549541069, 35.5059204731218, 
41.5333417555995, 27.6069075391361, 31.2404889715121, 27.8920960978598, 
37.8505531149324, 49.2616631533957, 30.366837650159, 31.1623492639066, 
55.0456078770405, 42.772538591063, 49.2419293590535, 26.1963523976241, 
54.4080781796616, 44.9796700541254, 34.6996927469131, 41.6227713664027, 
36.8449646519306, 27.5318686661673, 31.6641793552795, 42.8198894266632, 
40.5769177148146, 40.5769177148146, 29.3807781312816, 36.8579132935989, 
55.5617033901752, 55.8097119335638, 55.1041728261666, 43.6094641699075, 
37.0674887276681, 27.3876960746536), resid = c(-0.0575013282403773, 
1.69175252413213, 5.58184180815435, 0.709477307081826, 4.43237980997177, 
0.148291729320228, 1.34185017536599, 0.704588420467079, 1.60560242188613, 
-0.832954500001826, -2.50432781720766, 1.98509423559461, -7.93063902185855, 
1.29797631424874, -0.169581471276786, -1.51958147127679, -4.43498658815778, 
-3.08284267375831, 1.32406295383237, 5.09791764446704, -7.62707881801468, 
-0.189830893849219, -2.38311926659339, -0.541058328675241, -0.286897454014273, 
3.06825072495888, 3.38653649519422, 4.14399886836018, 10.1388117125598, 
3.03074619354486, 0.189991577733821, -1.82690753913609, 2.16617769515461, 
-0.088762764526507, 1.47611355173427, -0.268329820062384, -5.12350431682565, 
1.5076507360934, 0.124392122959534, 0.147461408936991, 5.34473730761318, 
-3.03635239762411, 10.1985884870051, -4.18300338745873, 4.31697391975358, 
0.0105619669306023, -0.958297985263961, -2.43186866616734, -8.38751268861282, 
1.64011057333683, -6.36025104814794, 0.226415618518729, -4.80411146461488, 
-1.1279132935989, 6.33496327649151, 6.37362139976954, 19.5424938405001, 
-4.17279750324084, -0.467488727668119, -0.254362741320246)), .Names = c("act", 
"pred", "resid"), row.names = c(2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 
10L, 11L, 12L, 13L, 15L, 16L, 17L, 18L, 19L, 20L, 21L, 22L, 23L, 
24L, 25L, 26L, 28L, 29L, 30L, 31L, 32L, 33L, 34L, 35L, 36L, 37L, 
38L, 39L, 41L, 42L, 43L, 44L, 45L, 46L, 47L, 48L, 49L, 50L, 51L, 
52L, 54L, 55L, 56L, 57L, 58L, 59L, 60L, 61L, 62L, 63L, 64L, 65L
), class = "data.frame")

Chỉ tò mò - tại sao không vẽ biểu đồ thực tế và số dư trong cùng một biểu đồ?
Ricardo Saporta

2
Tôi sẽ tạo các lô riêng biệt và sau đó sử dụng grid.arrange.
joran

@RicardoSaporta Có hình ảnh nào trên google mà bạn có thể liên kết đến làm ví dụ không? Bạn có đang đề xuất, bằng cách sử dụng dữ liệu sau khi tan chảy, mà tôi sẽ làm mà không cần quan tâm ggplot(plot, aes(x = pred, y = value)) + geom_point()đến không? Điều đó sẽ không thực sự thu nhỏ quy mô của phần dư để khó phát hiện ra sự không ngẫu nhiên / sai lệch?
Hendy

1
Bình luận khác của tôi là đánh bóng mặt mà được ít mã ... Tôi chỉ phải tan chảy, sau đó âm mưu và khía cạnh của variablegiá trị được tạo ra bởi melt(). Sau đó, một lần nữa, tôi cho rằng tôi có thể lưu trữ những thứ này trong một danh sách được tạo bởi lapplyđể vẽ các kết hợp khác nhau. Cảm ơn các đầu vào. Nếu bạn muốn tạo một gridgiải pháp, tôi có thể chấp nhận câu trả lời, mặc dù nếu đó là lộ trình chúng tôi thực hiện, thì đây cũng có thể là bản sao của các gridgiải pháp dựa trên cơ sở khác .
Hendy

1
@joran và tôi thấy rằng tôi thường khuyên mọi người không nên sử dụng grid.arrangethứ mà gần như luôn làm rối bố cục. Tôi ước gì các lỗi lâu nay của gtable được giải quyết.
baptiste

Câu trả lời:


115

Đây là một số mã có geom_blanklớp giả ,

range_act <- range(range(results$act), range(results$pred))

d <- reshape2::melt(results, id.vars = "pred")

dummy <- data.frame(pred = range_act, value = range_act,
                    variable = "act", stringsAsFactors=FALSE)

ggplot(d, aes(x = pred, y = value)) +
  facet_wrap(~variable, scales = "free") +
  geom_point(size = 2.5) + 
  geom_blank(data=dummy) + 
  theme_bw()

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


11
Một biến thể đẹp của nó là expand_limits(pred=range_act, value=range_act), sử dụng geom_blanknhưng đơn giản hơn để sử dụng.
ergon

6
Điều này chỉ mở rộng các giới hạn (nhưng không thu hẹp nó) Có cách nào để rút ngắn phạm vi không? @baptiste
Indranil Gayen

32

Tôi không chắc mình hiểu bạn muốn gì, nhưng dựa trên những gì tôi đã hiểu

thang x có vẻ giống nhau, đó là thang y không giống nhau và đó là do bạn đã chỉ định scale = "free"

bạn có thể chỉ định scale = "free_x" để chỉ cho phép x miễn phí (trong trường hợp này, nó giống như pred có cùng phạm vi theo định nghĩa)

p <- ggplot(plot, aes(x = pred, y = value)) + geom_point(size = 2.5) + theme_bw()
p <- p + facet_wrap(~variable, scales = "free_x")

đã làm việc cho tôi, xem hình ảnh

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

Tôi nghĩ rằng bạn đã làm quá khó khăn - tôi dường như nhớ một lần xác định các giới hạn dựa trên một công thức với tối thiểu và tối đa và nếu có khía cạnh, tôi nghĩ rằng nó chỉ sử dụng những giá trị đó, nhưng tôi không thể tìm thấy mã


7

Bạn cũng có thể chỉ định phạm vi bằng lệnh coord_cartesian để đặt phạm vi trục y mà bạn muốn, giống như trong bài trước, sử dụng scale = free_x

p <- ggplot(plot, aes(x = pred, y = value)) +
     geom_point(size = 2.5) +
     theme_bw()+
     coord_cartesian(ylim = c(-20, 80))
p <- p + facet_wrap(~variable, scales = "free_x")
p

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.