2009-07-11 8 views
6

У меня есть data.frame с 2 колонками: узел А, узел B. Каждая запись в кадре означает ребро в графе между узлом А и В.Создание списка смежности из data.frame

Там должен быть хорошим однострочным конвертером для преобразования этого data.frame в список смежности. Любые намеки?

ответ

6

Быстрый и грязный ...

> edges <- data.frame(nodea=c(1,2,4,2,1), nodeb=c(1,2,3,4,5)) 

> adjlist <- by(edges, edges$nodea, function(x) x$nodeb) 

> for (i in as.character(unique(edges$nodea))) { 
+ cat(i, ' -> ', adjlist[[i]], '\n') 
+ } 

1 -> 1 5 
2 -> 2 4 
4 -> 3 

> adjlist 
edges$nodea: 1 
[1] 1 5 
------------------------------------------------------------ 
edges$nodea: 2 
[1] 2 4 
------------------------------------------------------------ 
edges$nodea: 4 
[1] 3 
+0

Guh. Ага. Это идеальный лайнер. Как ни странно, мое решение для цикла работает в два раза быстрее, чем by(). –

+0

действительно не очень быстро, когда ваш стол длиннее 50 000 (с ~ 5000 идентификаторами). Существуют ли более быстрые альтернативы? –

0

как бы вы представляли список смежности в R? ему нужны списки переменного размера для набора соседних узлов; поэтому вам нужно использовать список(); но тогда, какая польза от него в R?

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

> edgelist=data.frame(A=c(1,1,2,2,2),B=c(1,2,2,3,4)) 
> library(plyr) 
> llply(1:max(edgelist), function(a) list(node=a, adjacents=as.list(edgelist$B[edgelist$A==a]))) 
[[1]] 
[[1]]$node 
[1] 1 

[[1]]$adjacents 
[[1]]$adjacents[[1]] 
[1] 1 

[[1]]$adjacents[[2]] 
[1] 2 



[[2]] 
[[2]]$node 
[1] 2 

[[2]]$adjacents 
[[2]]$adjacents[[1]] 
[1] 2 

[[2]]$adjacents[[2]] 
[1] 3 

[[2]]$adjacents[[3]] 
[1] 4 



[[3]] 
[[3]]$node 
[1] 3 

[[3]]$adjacents 
list() 


[[4]] 
[[4]]$node 
[1] 4 

[[4]]$adjacents 
list() 
+0

Брендан - стандартная (по крайней мере, с igraph) точка зрения представляет собой список вершин - и каждый элемент списка представляет собой вектор смежных вершин. –

4
> edges <- data.frame(nodea=c(1,2,4,2,1), nodeb=c(1,2,3,4,5)) 

> attach(edges) 

> tapply(nodeb,nodea,unique) 

$`1` 
[1] 1 5 

$`2` 
[1] 2 4 

$`4` 
[1] 3 
+0

по какой-то странной причине, встроенной в R 'tapply (as.character (nodeb), as.character (nodea), unique)' в 100 раз быстрее при преобразовании моей очень длинной таблицы (100 000 строк) в список, чем 'tapply (NodeB, узел А, уникальный) '!!! –

11

Поскольку вы помечено этот , как об использовании встроенных функций?

> g <- graph.data.frame(edges) 
> adjlist <- get.adjedgelist(g) 

Только оговорка - это вершины с нулевым индексом, которые будут меняться с помощью igraph 0.6.