2015-03-04 8 views
1

из data.frame (или любого другого типа объекта R) с 3 столбцами: «Node, Parent и text», я бы хотел построить дерево с строками от «Node» до «Parent "и" текст "в качестве метки.Дерево с R

Может кто-нибудь предложить хорошую библиотеку для использования и пример кода, если это возможно. Я смотрю на библиотеку igraph, но все примеры, которые я мог найти, нарисовать деревья с последовательными числами или буквами в виде узлов, а не просто установить макет дерева.

Любая помощь будет принята с благодарностью

Благодаря

EDIT:

Спасибо, ребята за вашу помощь, я действительно ценю это. Дополнительные комментарии, если вы можете помочь

@ md1630, я попробовал ваше предложение, но это не то, что я ищу. В коде кулака дерево с корнем сверху и стрелки от корня до листа, а второе исправляет стрелки, но инвертирует дерево. То, что я хотел бы это корень сверху и стрелка от листьев к корню (Я понимаю, что не может быть деревом на скажем - но это требование

enter image description here

@ user20650 ваше решение выглядит правильно, но начинается изображение чтобы получить переполненность по мере увеличения количества узлов. Любая идея о том, как добавить больше пространства между ними? enter image description here

@math Я использую функцию, которую вы предоставили правильно? Я назвал plot (layout.binary (g)) и получил (слева), справа - выход графика (г)

enter image description here

+0

Вы можете использовать 'igraph'. Используйте 'graph.data.frame' для создания графика, установите метки границ в вызове' plot' с помощью 'edge.label = E (g) $ text' и получите макет дерева с' layout.reingold.tilford' – user20650

ответ

2

Вы можете использовать rgraphviz. Вот код для построения дерева из dataframe df с столбцами «Node, Parent и text». Я не запускал это на своем компьютере, поэтому могут быть ошибки. Но примерно это идея:

source("http://bioconductor.org/biocLite.R") 
biocLite("Rgraphviz") 
library("Rgraphviz") 
#first set up the graph with just the nodes 
nodes<- unique(df['Node']) 
gR <- new("graphNEL", nodes = nodes, edgemode = "directed") 
#add edges for each row in df 
    for (j in (1:nrow(df))) { 
     gR <- addEdge(df[j,2], df[j,1], gR, 1) 
    } 
#add text labels 
nAttrs <- list() 
z <- df['text'] 
nAttrs$label <- z 
#plot 
plot(gR, nodeAttrs = nAttrs) #you can specify more attributes here 
+0

спасибо очень! две вещи: этот код разбивает дерево вверх дном (корень внизу) - знаете ли вы, как поставить его сверху? Кроме того, часть ярлыка, похоже, не работает, любая идея почему? – Diego

+0

О, извините, функция addEdge была неправильной. addEdge - addEdge (from, to, graph, weight). Поэтому он должен добавить ребро от родителя к узлу, а не наоборот. Я только что редактировал свой пост. Он должен работать теперь, надеюсь, – md1630

+0

спасибо md, я пробовал это, но он все еще не работает. Посмотрите на редактирование – Diego

0

Вы можете использовать igraph, чтобы получить сеть с вашими данными (предположим, ваш dataframe является dd):

g = graph(t(dd[,2:1])) 
V(g)$label = as.character(dd$text) 
plot(g, layout=layout.binary) 

я должен свой корень (без родителей) является а не в кадре данных, в противном случае используйте вместо этого dd[-1,2:1].

Если вы хотите иметь дерево, вы можете легко создать макет, это просто функция, которая берет график и возвращает матрицу. Для бинарного дерева:

layout.binary = function(graph) { 
    layout = c() 
    r_vertex = length(V(graph)) 
    depth = ceiling(log2(r_vertex+1)) 
    for (ii in 0:(depth-1)) { 
     for (jj in 1:min(2^ii, r_vertex)) { 
      layout = rbind(layout, c(ii, (2*(jj-1)+1)/(2^(ii+1)))) 
     } 
     r_vertex = r_vertex - 2^ii 
    } 
    return(layout) 
} 

Он будет строить горизонтальное дерево, используйте c((2*(jj-1)+1)/(2^(ii+1)), ii), если вы хотите быть в вертикальном положении.

+0

Спасибо math, но просто вызов g = graph (t (c [, 2: 1])) возвращает «не может создать пустой граф с отрицательным числом вершин», ошибка; t (c [, 2: 1]) возвращает [, 1] [, 2] Родитель «A» «A» Узел «B» «C» – Diego

+0

Вероятно, потому, что ваши столбцы «Node» и «Parent» имеют символы вместо цифр, используйте 'g = graph (matrix (c (as.factor (dd [, 2]), as.factor (dd [, 1])), nrow = 2, byrow = T))' исправить Это. (потому что 'graph' вызывает' as.numeric', и он дает 'NA' для символа, но число для коэффициентов) – Math

+0

да, но тогда коэффициент as учитывает коэффициент вместо строки .... также Im not конечно, если Im правильно использует функцию. Можете ли вы взглянуть на редактирование? спасибо – Diego

2

комментарий обновления

library(igraph) 

# some example data 
dat <- data.frame(parent=rep(letters[1:3], each=2), 
        node=letters[2:7], 
        text=paste0("lab", 1:6)) 
# create graph 
g <- graph.data.frame(dat) 

# plot 
# layout.reingold.tilford gives a tree structure 
# edge and vertx labels can be defined in the plot command or alternatively 
# you can add them to the graph via V(g)$name and E(g($label assignments 

plot(g, layout = layout.reingold.tilford, 
      edge.label=E(g)$text, vertex.label=paste0("v_lab",1:7)) 

EDIT повторно комментарий

Если вы хотите, чтобы направление идти из листьев по направлению к корню; сначала вы можете получить координаты расположения дерева из более стандартной древовидной структуры, а затем перевернуть границы.

# get tree layout coords 
g <- graph.data.frame(dat) 
lay = layout.reingold.tilford(g) 

# redraw graph with edges reversed 
g2 <- graph.data.frame(dat[2:1], vertices = get.data.frame(g, what="vertices")) 

par(mar=rep(0,4), mfrow=c(1,2)) 
plot(g, layout=lay) 
plot(g2, layout=lay) 

enter image description here

+0

это здорово, единственное, что стрелки перевернуты; поэтому первая строка на «dat» - «текст родительского узла» «a b lab1»; и стрелка в отчете идет от a до b, и это должно быть наоборот. Когда я попытался реализовать изменение, он скремблировал весь макет. Есть предположения? Спасибо – Diego

+0

Итак, вы хотите «дерево» с направлением ребер, идущих от 'листьев' до' root'? – user20650

+0

спасибо пользователю. У меня есть другой вопрос относительно макета, можете ли вы взглянуть на редактирование? – Diego