2017-05-04 9 views
16

में घुमावदार लाइनों का उपयोग करें मैं समय के साथ रैंकिंग दिखाने के लिए एक बाम्प चार्ट (parallel coordinates लेकिन निरंतर एक्स-अक्ष के साथ) बनाने की कोशिश कर रहा हूं। मैं बहुत आसानी से एक सरल-रेखा चार्ट बना सकते हैं:बंप चार्ट

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() 

कमाल। अब, हालांकि, मैं कनेक्टिंग लाइन घुमावदार बनाना चाहता हूँ। प्रति x एक से अधिक y होने के बावजूद, geom_smooth कुछ संभावनाएं प्रदान करता है। loess ऐसा लगता है कि इसे काम करना चाहिए, क्योंकि यह निकटतम को छोड़कर बिंदुओं को अनदेखा कर सकता है। हालांकि, यहां तक ​​सबसे अच्छा मैं अभी भी बहुत से बिंदु याद करते हैं और दूसरों को जहां वह प्रतिक्रिया होना चाहिए overshoots प्राप्त कर सकते हैं में सुधार करने के साथ:

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

मैं अन्य splines के एक नंबर की कोशिश की है ggalt::geom_xspline की तरह, है, लेकिन वे सब अभी भी लक्ष्य के पार चले या अंक याद आती है:

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

वहाँ वक्र लिए एक आसान तरीका है ये लाइनें? क्या मुझे अपनी खुद की सिग्मोडाइड स्पलीन बनाने की ज़रूरत है? स्पष्ट करने के लिए, मैं D3.js's d3.curveMonotoneX की तरह कुछ है जो हर बिंदु और जिसका स्थानीय मॅक्सिमा और न्यूनतम y मूल्यों से अधिक नहीं है हिट की तलाश में हूँ:

d3.curveMonotoneX image

आदर्श रूप में यह शायद प्रत्येक बिंदु पर 0 से ढलान है, भी, लेकिन यह बिल्कुल जरूरी नहीं है।

+0

के अनुसार [इस उत्तर] (https://stats.stackexchange.com/a/29442) - किस बारे में 'cobs' पैकेज? "सीओबीएस सीमित बी-स्प्लिंस के लिए खड़ा है। संभावित बाधाओं में विशिष्ट बिंदुओं के माध्यम से जाना, निर्दिष्ट मूल्यों के लिए डेरिवेटिव सेट करना, एकात्मकता (बढ़ती या घटाना), अव्यवस्था, उत्परिवर्तन, आवधिकता इत्यादि शामिल हैं।" मैं इसे तुरंत काम नहीं कर सकता लेकिन वादा करता हूं। –

+0

ओह, यह आशाजनक लग रहा है। मैं 'fda :: smooth.monotone' की कोशिश कर रहा था, लेकिन इसके पैरामीटर हास्यास्पद रूप से जटिल हैं। – alistaire

+0

मुझे लगता है कि आप डिग्री को tweaking और span 'geom_smooth (method = 'loess', span = 0.3, se = FALSE, method.args = list (डिग्री = 1)) ' – user2957945

उत्तर

22

एक्स-वैल्यू कार्यों के ग्रिड के साथ signal::pchip का उपयोग करके, कम से कम आपके उदाहरण में संख्यात्मक अक्ष के साथ। एक उचित geom_ अच्छा होगा, लेकिन हे ...

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() 

परिणाम: Result

+2

सुंदर! मुझे कहना है, मुझे लगता है कि मैंने कभी देखा है कि यह सबसे अच्छा पहला जवाब है। कुछ मामूली चालबाजी के साथ, आप इसे सभी को ggplot में भी हैक कर सकते हैं: 'ggplot (df, aes (Var2, रैंक, रंग = Var1)) + geom_point() + lapply (विभाजन (डीएफ, डीएफ $ Var1), फ़ंक्शन (। डेटा) {stat_function (एईएस (रंग = Var1), .data, fun = function (x) {signal :: pchip (.data $ Var2, .data $ रैंक, x)})} ' – alistaire

संबंधित मुद्दे