2015-08-17 1 views
7

Пусть Я хотел бы произвести своего рода древовидной структуры, как показано ниже:Соединение двух точек с изогнутыми линиями (S-МОГ кривой) в R

plot(0, type="n",xlim=c(0, 5), ylim=c(-3, 8), axes=FALSE, xlab="", ylab="", main="") 
points(1, 2.5) 
points(3, 5) 
points(3, 0) 
lines(c(1, 3), c(2.5, 5)) 
lines(c(1, 3), c(2.5, 0)) 
text(1, 2.5, adj=1, label="Parent ") 
text(3, 5, adj=0, label=" Child 1") 
text(3, 0, adj=0, label=" Child 2") 

enter image description here

Интересно, если есть способ в R, где мы можем создавать кривые линии, которые по-разному напоминают S-образную кривую, как показано ниже. Существенно было бы здорово, если бы можно было создать такие линии, не прибегая к ggplot.

enter image description here

EDIT удалены и сделал в ответ

+0

Это хороший редактировать! Я мог бы украсть это на самом деле. Вы должны сделать свое редактирование ответом и принять его самостоятельно - безусловно, достойный upvote или 3. – thelatemail

+0

@thelatemail: Спасибо за предложение. Я добавил свой ответ и включил чуть более подробный пример. – Alex

ответ

8

По предложению @ thelatemail, я решил сделать мой редактировать в ответ. Мое решение основано на ответе @ thelatemail.

я написал небольшую функцию, чтобы рисовать кривые, что делает использование логистической функции:

#Create the function 
curveMaker <- function(x1, y1, x2, y2, ...){ 
    curve(plogis(x, scale = 0.08, loc = (x1 + x2) /2) * (y2-y1) + y1, 
        x1, x2, add = TRUE, ...) 
} 

рабочий пример ниже. В этом примере я хочу создать график для таксономии с тремя уровнями: parent ->2 children ->20 grandchildren. У одного ребенка есть 12 внуков, а у другого ребенка 8 детей.

#Prepare data: 
parent <- c(1, 16) 
children <- cbind(2, c(8, 28)) 
grandchildren <- cbind(3, (1:20)*2-1) 
labels <- c("Parent ", paste("Child ", 1:2), paste(" Grandchild", 1:20)) 


#Make a blank plot canvas 
plot(0, type="n", ann = FALSE, xlim = c(0.5, 3.5), ylim = c(0.5, 39.5), axes = FALSE) 

#Plot curves 
#Parent and children 
invisible(mapply(curveMaker, 
        x1 = parent[ 1 ], 
        y1 = parent[ 2 ], 
        x2 = children[ , 1 ], 
        y2 = children[ , 2 ], 
        col = gray(0.6, alpha = 0.6), lwd = 1.5)) 

#Children and grandchildren 
invisible(mapply(curveMaker, 
        x1 = children[ 1, 1 ], 
        y1 = children[ 1, 2 ], 
        x2 = grandchildren[ 1:8 , 1 ], 
        y2 = grandchildren[ 1:8, 2 ], 
        col = gray(0.6, alpha = 0.6), lwd = 1.5)) 
invisible(mapply(curveMaker, 
        x1 = children[ 2, 1 ], 
        y1 = children[ 2, 2 ], 
        x2 = grandchildren[ 9:20 , 1 ], 
        y2 = grandchildren[ 9:20, 2 ], 
        col = gray(0.6, alpha = 0.6), lwd = 1.5)) 
#Plot text 
text(x = c(parent[1], children[,1], grandchildren[,1]), 
     y = c(parent[2], children[,2], grandchildren[,2]), 
     labels = labels, 
     pos = rep(c(2, 4), c(3, 20))) 

#Plot points 
points(x = c(parent[1], children[,1], grandchildren[,1]), 
     y = c(parent[2], children[,2], grandchildren[,2]), 
     pch = 21, bg = "white", col="#3182bd", lwd=2.5, cex=1) 

enter image description here

4

звучит как кривой сигмовидной и т.д .:

f <- function(x,s) s/(1 + exp(-x)) 
curve(f(x,s=1),xlim=c(-4,4)) 
curve(f(x,s=0.9),xlim=c(-4,4),add=TRUE) 
curve(f(x,s=0.8),xlim=c(-4,4),add=TRUE) 
curve(f(x,s=0.7),xlim=c(-4,4),add=TRUE) 

Результат:

enter image description here

Вы можете начать адаптировать это, например. вот неуклюжий бит кода:

plot(NA,type="n",ann=FALSE,axes=FALSE,xlim=c(-6,6),ylim=c(0,1)) 
curve(f(x,s=1),xlim=c(-4,4),add=TRUE) 
curve(f(x,s=0.8),xlim=c(-4,4),add=TRUE) 
curve(f(x,s=0.6),xlim=c(-4,4),add=TRUE) 
text(
    c(-4,rep(4,3)), 
    c(0,f(c(4),c(1,0.8,0.6))), 
    labels=c("Parent","Kid 1","Kid 2","Kid 3"), 
    pos=c(2,4,4,4) 
) 

Результат:

enter image description here

+0

Спасибо! Есть ли способ указать не только координаты конечной точки, но и координаты начальной точки кривой? Предположим, что вместо этого, начиная с 'x = 0' и' y = 0', я хотел бы начать с 'x = 1' &' y = 5' (и заканчивать на 'x = 5' &' y = 20') , – Alex

+1

@Alex - Мне кажется, вам нужно что-то вроде этого: https://en.wikipedia.org/wiki/Generalised_logistic_function как функция кривой – thelatemail

+0

Спасибо! Логистическая функция - вот что я сделал для меня. – Alex

4

Я думаю, что Пол Мюррелл есть документ, иллюстрирующий подобные диаграммы в сетке. Вот простой пример,

enter image description here

library(grid) 

labelGrob <- function(x,y,label, ...){ 
    t <- textGrob(x,y,label=label) 
    w <- convertWidth(1.5*grobWidth(t), "npc", valueOnly = TRUE) 
    h <- convertHeight(1.5*grobHeight(t), "npc", valueOnly = TRUE) 
    gTree(cl = "label", west = unit(x-0.5*w, "npc"), 
     east = unit(x+0.5*w, "npc"), 
     children=gList(t, roundrectGrob(x=x, y=y, gp=gpar(fill=NA), 
             width=w, height=h))) 

} 

xDetails.label <- function(x, theta){ 
    if(theta == 180) return(x$west[1]) else 
    if(theta == 0) return(x$east[1]) else 
    xDetails(x$children[[1]], theta) 
} 

yDetails.label <- function(x, theta){ 
    if(theta %in% c("west", "east")) return(x$y) else 
    yDetails(x$children[[1]], theta) 
} 

lab1 <- labelGrob(0.1, 0.5, "start") 
lab2 <- labelGrob(0.6, 0.75, "end") 
grid.newpage() 
grid.draw(lab1) 
grid.draw(lab2) 
grid.curve(grobX(lab1, "east"), grobY(lab1, "east"), 
      grobX(lab2, "west"), grobY(lab2, "west"), 
      inflect = TRUE, curvature=0.1) 
+0

Очень приятно. Пользовательские методы '(x | y) Details' являются esp. элегантный контакт! –