首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在凹凸图表中使用曲线

在凹凸图表中使用曲线
EN

Stack Overflow用户
提问于 2017-05-04 08:19:26
回答 2查看 1.7K关注 0票数 18

我正在尝试制作一个凹凸图(类似于parallel coordinates,但有一个有序的x轴)来显示一段时间内的排名。我可以很容易地画一张直线图:

代码语言:javascript
复制
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看起来应该可以工作,因为它可以忽略除了最近的点之外的点。然而,即使调整了我能得到的最好的,我仍然错过了很多点,并在它应该是平坦的地方超过了其他人:

代码语言:javascript
复制
ggplot(df, aes(Var2, rank, color = Var1)) + 
    geom_smooth(method = 'loess', span = .7, se = FALSE) + 
    geom_point()

我已经尝试了很多其他的样条线,比如ggalt::geom_xspline,但是它们仍然都超调或者没有切中要点:

代码语言:javascript
复制
ggplot(df, aes(Var2, rank, color = Var1)) + ggalt::geom_xspline() + geom_point()

有没有一种简单的方法来弯曲这些线?我需要构建我自己的sigmoidal样条曲线吗?为了澄清,我正在寻找像D3.js's d3.curveMonotoneX这样的东西,它命中每个点,并且其局部最大值和最小值不超过y值:

理想情况下,它在每个点的斜率也可能为0,但这并不是绝对必要的。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-05-04 16:48:20

使用带有X值网格的signal::pchip是可行的,至少在使用数值轴的示例中是这样的。一个合适的geom_会很好,但是嘿...

代码语言:javascript
复制
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()

结果:

票数 23
EN

Stack Overflow用户

发布于 2019-01-09 20:10:45

基于亨里克的回答,这是对pchip的总结(我在这里使用的是来自pracma的方法,但结果是相同的),因此它可以更容易地与现有的平滑方法一起使用:

代码语言:javascript
复制
ggpchip = function(formula, data, weights) structure(pracma::pchipfun(data$x, data$y), class='ggpchip')
predict.ggpchip = function(object, newdata, se.fit=F, ...) {
  fit = unclass(object)(newdata$x)
  if (se.fit) list(fit=data.frame(fit, lwr=fit, upr=fit), se.fit=fit * 0) else fit
}

那么实际的ggplot调用就很简单了:

代码语言:javascript
复制
ggplot(df, aes(Var2, rank, color=Var1)) + geom_smooth(method='ggpchip', se=F) + geom_point()

然后你可以使用pchip来平滑其他的geoms,例如面积图:

代码语言:javascript
复制
ggplot(df, aes(Var2, rank, fill=Var1)) + stat_smooth(method='ggpchip', geom='area', position='fill')
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43771900

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档