2017-05-04 33 views
16

我試圖製作一個顛簸圖表(如parallel coordinates但帶有連續的x軸)以顯示隨着時間的推移排名。我可以做一個直線圖很容易:在顛簸圖表中使用曲線

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似乎應該工作,因爲它可以忽略除最近的點之外的點。然而,即使有調整最好的,我可以得到還惦記着大量的點和過沖等,它應該是平的:

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

我已經嘗試了一些其他的花鍵,如ggalt::geom_xspline,但他們都還過沖或錯過點:

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

有一種簡單的方式來曲線這些線?我是否需要構建自己的S形樣條?爲了澄清,我正在尋找類似D3.js's d3.curveMonotoneX這傷害到每一個點,其局部最大值和最小值不超過y值:

d3.curveMonotoneX image

理想的話,大概有0斜率在每個點,也是,但這不是絕對必要的。

+0

按[這個答案](https://stats.stackexchange.com/a/29442) - 怎麼樣'cobs'包? 「COBS代表約束B樣條,可能的約束條件包括經過特定點,將導數設置爲指定值,單調性(增大或減小),凹度,凸度,週期性等。我無法立即開始工作,但有承諾。 –

+0

哦,看起來很有希望。我正在嘗試'fda :: smooth.monotone',但它的參數非常複雜。 – alistaire

+0

我認爲你可以通過調整度數和範圍'geom_smooth(method ='loess',span = 0.3,se = FALSE,method.args = list(degree = 1))來做到這一點' – user2957945

回答

22

使用帶有X值網格的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(var,rank,color = Var1))+ geom_point()+ lapply(split(df,df $ Var1),function(。數據){stat_function(aes(color = Var1),.data,fun = function(x){signal :: pchip(.data $ Var2,.data $ rank,x)})})'' – alistaire