2016-08-04 145 views
1

我想創建一個sankey-like情節,我可以在ggplot2中創建起始位置和終止位置之間有曲線的位置。目前,我有一個看起來像這樣的數據:爲ggplot2插入起點和終點之間的曲線

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

have

我會喜歡看到這樣的數據:

enter image description here

這是用於設置數據的另一選擇:

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/

預先感謝您!

回答

2

下面的代碼通過邏輯函數創建曲線。你可以使用你喜歡的任何功能,但這是主要想法。我應該注意,除了圖形目的以外,創建一個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)) 

enter image description here

+0

我不完全理解它是如何工作的,但它似乎做的伎倆!我會注意到你的評論:這表明了這種關係。我也想承認你回答這個問題的速度,這是相當令人欽佩的! – yake84

相關問題