【问题标题】:Interpolate curved line betweenstart and end points for ggplot2在ggplot2的起点和终点之间插入曲线
【发布时间】:2016-08-05 01:18:25
【问题描述】:

我想创建一个可以在 ggplot2 中创建的类似 sankey 的图,其中我的起点和终点位置之间有曲线。目前,我的数据如下所示:

df <- data.frame(Line = rep(letters[1:4], 2),
                 Location = rep(c("Start", "End"), each=4),
                 X = rep(c(1, 10), each = 4),
                 Y = c(c(1,3, 5, 15), c(9,12, 14, 6)),
                 stringsAsFactors = F)

例如:

  Line Location  X Y
1    a    Start  1 1
2    a      End 10 9

并创建一个看起来像这样的图:

library(ggplot2)
ggplot(df) +
  geom_path(aes(x= X, y= Y, group = Line))

我希望看到这样的数据:

这是设置数据的另一个选项:

df2 <- data.frame(Line = letters[1:4],
                  Start.X= rep(1, 4),
                  Start.Y = c(1,3,5,15),
                  End.X = rep(10, 4),
                  End.Y = c(9,12,14,6))

例如:

  Line Start.X Start.Y End.X End.Y
1    a       1       1    10     9

我可以找到如何将曲线添加到基础 R 图形的示例,但这些示例并未演示如何获取中间点的数据框以绘制该曲线。我更喜欢使用dplyr 进行数据操作。我想这将需要一个 for 循环来构建一个插值表。

这些示例相似,但不会产生 s 形曲线:

Plotting lines on map - gcIntermediate

http://flowingdata.com/2011/05/11/how-to-map-connections-with-great-circles/

提前谢谢你!

【问题讨论】:

    标签: r ggplot2


    【解决方案1】:

    下面的代码通过逻辑函数创建曲线。您可以使用您喜欢的任何功能,但这是主要思想。我应该注意,除了图形目的之外,用 2 个点创建一条曲线是个坏主意。它暗示数据显示了某种类型的关系,而实际上并不暗示这种关系。

    df <- data.frame(Line = rep(letters[1:4], 2),
                     Location = rep(c("Start", "End"), each=4),
                     X = rep(c(1, 10), each = 4),
                     Y = c(c(1,3, 5, 15), c(9,12, 14, 6)),
                     stringsAsFactors = F)
    
    # logistic function for curved lines
    logistic = function(x, y, midpoint = mean(x)) {
      ry = range(y)
      if (y[1] < y[2]) {
        sign = 2
      } else {
        sign = -2
      }
      steepness = sign*diff(range(x)) / diff(ry)
      out = (ry[2] - ry[1]) / (1 + exp(-steepness * (x - midpoint))) + ry[1]
      return(out)
    }
    
    # an example
    x = c(1, 10)
    y = c(1, 9)
    xnew = seq(1, 10, .5)
    ynew = logistic(xnew, y)
    plot(x, y, type = 'b', bty = 'n', las = 1)
    lines(xnew, ynew, col = 2, type = 'b')
    
    # applying the function to your example
    xnew = seq(min(df$X), max(df$X), .1) # new x grid
    m = matrix(NA, length(xnew), 4) # matrix to store results
    
    uniq = unique(df$Line) # loop over all unique values in df$Line
    for (i in seq_along(uniq)) {
      m[, i] = logistic(xnew, df$Y[df$Line == uniq[i]])
    }
    # base R plot
    matplot(xnew, m, type = 'b', las = 1, bty = 'n', pch = 1)
    
    # put stuff in a dataframe for ggplot
    df2 = data.frame(x = rep(xnew, ncol(m)), 
                     y = c(m), 
                     group = factor(rep(1:ncol(m), each = nrow(m))))
    
    library(ggplot2)
    ggplot(df) +
      geom_path(aes(x= X, y= Y, group = Line, color = Line)) +
      geom_line(data = df2, aes(x = x, y = y, group = group, color = group))
    

    【讨论】:

    • 我不完全理解这是如何工作的,但它似乎可以解决问题!我会记下您的评论:这表明的关系。我也想承认你回答这个问题的速度,非常令人钦佩!
    猜你喜欢
    • 2015-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-27
    • 1970-01-01
    • 2015-04-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多