2017-05-04 17 views
16

Tôi đang cố tạo biểu đồ hình tròn (như parallel coordinates nhưng với trục x liên tục) để hiển thị xếp hạng theo thời gian. Tôi có thể làm cho một biểu đồ đường thẳng rất dễ dàng:Sử dụng các đường cong trong biểu đồ va chạm

library(ggplot2) 
set.seed(47) 

df <- as.data.frame(as.table(replicate(8, sample(4))), responseName = 'rank') 
df$Var2 <- as.integer(df$Var2) 

head(df) 
#> Var1 Var2 rank 
#> 1 A 1 4 
#> 2 B 1 2 
#> 3 C 1 3 
#> 4 D 1 1 
#> 5 A 2 3 
#> 6 B 2 4 

ggplot(df, aes(Var2, rank, color = Var1)) + geom_line() + geom_point() 

tuyệt vời. Bây giờ, mặc dù, tôi muốn làm cho các đường kết nối cong. Mặc dù không bao giờ có nhiều hơn một y mỗi x, geom_smooth cung cấp một số khả năng. loess có vẻ như nó sẽ hoạt động, vì nó có thể bỏ qua các điểm ngoại trừ điểm gần nhất. Tuy nhiên, ngay cả với tinh chỉnh tốt nhất mà tôi có thể nhận được vẫn còn nhớ rất nhiều điểm và overshoots người khác mà nó nên được bằng phẳng:

ggplot(df, aes(Var2, rank, color = Var1)) + 
    geom_smooth(method = 'loess', span = .7, se = FALSE) + 
    geom_point() 

Tôi đã thử một số splines khác, như ggalt::geom_xspline, nhưng tất cả họ đều vẫn vọt lố hoặc bỏ lỡ điểm:

ggplot(df, aes(Var2, rank, color = Var1)) + ggalt::geom_xspline() + geom_point() 

có một cách dễ dàng để đường cong những dòng này? Tôi có cần xây dựng spline sigmoidal của riêng mình không? Để làm rõ, tôi đang tìm một cái gì đó giống như D3.js's d3.curveMonotoneX mà lượt truy cập tất cả các điểm và có địa phương cực đại và cực tiểu không vượt quá các giá trị y:

d3.curveMonotoneX image

Lý tưởng nhất là nó có lẽ sẽ có một độ dốc từ 0 tại mỗi điểm, quá, nhưng điều đó không thực sự cần thiết.

+0

Theo [câu trả lời này] (https://stats.stackexchange.com/a/29442) - những gì về gói 'cobs'? "COBS là viết tắt của các ràng buộc B-ràng buộc. Các ràng buộc có thể bao gồm đi qua các điểm cụ thể, thiết lập các dẫn xuất đến các giá trị được chỉ định, đơn điệu (tăng hoặc giảm), concavity, lồi, chu kỳ, vv" Tôi không thể ngay lập tức làm cho nó hoạt động nhưng có lời hứa. –

+0

Ooh, có vẻ đầy hứa hẹn. Tôi đã thử 'fda :: smooth.monotone', nhưng các tham số của nó phức tạp một cách lố bịch. – alistaire

+0

tôi nghĩ rằng bạn có thể làm điều này với loess bằng cách tinh chỉnh mức độ và khoảng 'geom_smooth (phương pháp = 'loess', span = 0,3, se = FALSE, method.args = list (độ = 1))' – user2957945

Trả lời

22

Sử dụng signal::pchip với một mạng lưới giá trị X hoạt động, ít nhất trong ví dụ của bạn với trục số. Một hợp geom_ sẽ được tốt đẹp, nhưng hey ...

library(tidyverse) 
library(signal) 
set.seed(47) 

df <- as.data.frame(as.table(replicate(8, sample(4))), responseName = 'rank') 
df$Var2 <- as.integer(df$Var2) 

head(df) 
#> Var1 Var2 rank 
#> 1 A 1 4 
#> 2 B 1 2 
#> 3 C 1 3 
#> 4 D 1 1 
#> 5 A 2 3 
#> 6 B 2 4 

ggplot(df, aes(Var2, rank, color = Var1)) + 
    geom_line(data = df %>% 
       group_by(Var1) %>% 
       do({ 
       tibble(Var2 = seq(min(.$Var2), max(.$Var2),length.out=100), 
         rank = pchip(.$Var2, .$rank, Var2)) 
       })) + 
    geom_point() 

Kết quả: Result

+2

Đẹp! Tôi phải nói, tôi nghĩ đây là câu trả lời đầu tiên tốt nhất mà tôi từng thấy. Với một số mẹo nhỏ, bạn có thể hack tất cả vào ggplot, quá: 'ggplot (df, aes (Var2, rank, color = Var1)) + geom_point() + lapply (split (df, df $ Var1), function (. dữ liệu) {stat_function (aes (màu = Var1), .data, fun = function (x) {signal :: pchip (.data $ Var2, .data $ rank, x)})}) ' – alistaire

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