2

给定分层数据,如下所示:

nodes <- data.frame(node_id=c(1,2,3),node_label=c('a','a','b'))
arcs <- data.frame(arc_id=c(1,2),from_node_id=c(1,2),to_node_id=c(2,3))

R以下最接近的解决方案是SQL VIEW什么?

(所以不仅仅是一个新的data.frame,还有确保数据完整性的机制,如SQL VIEW

CREATE VIEW AS
SELECT
    arcs.*,
    from_node.node_label,
    to_node.node_label
FROM
    arcs
    JOIN nodes AS from_node ON
        arcs.from_node_id = from_node.node_id
    JOIN nodes AS to_node ON
        arcs.to_node_id = to_node.node_id;

或者作为一个更好的定义,如果merge()没有循环或临时变量,以下如何可能?

merge(arcs,data.frame(label='e'),by.x='from_node_label',by.y='label')

我试过的:

  • 如果我试图直接访问这两个数据帧,如下所示,许多矩阵运算就会变成循环。

    nodes[nodes$node_id=arcs[i,]$from_node_label,]
    
  • 如果使用嵌套数据框,例如arcs$from_node <- node[c(1,2),],这看起来很有希望,但数据需要手动更新,并且仍然不允许合并

    > merge(arcs,data.frame(label='e'),by.x='from_node$label',by.y='label')
    Error in fix.by(by.x, x) : 'by' must specify uniquely valid column(s)
    
  • 最后,我使用以下两个函数将数据框展开为非规范化的“视图”,并在完成后折叠它。唯一的问题是我仍然必须手动保证受影响的列在数据框“扩展”时不会改变。

    expand_arcs <- function(nodes,arcs) {
        from_nodes <- nodes
        names(from_nodes) <- paste('from',names(from_nodes),sep='_')
    
        to_nodes <- nodes
        names(to_nodes) <- paste('to',names(to_nodes),sep='_')
    
        arcs <- merge(merge(
            arcs,
            from_nodes),
            to_nodes)
    
        return(list(nodes,arcs))
    }
    
    collapse_arcs <- function(nodes,arcs) {
        arcs <- arcs[c('arc_id','from_node_id','to_node_id')]
    
        return(list(nodes,arcs))
    }
    
4

2 回答 2

4

您可以在 sql 中翻译您的代码,但更容易使用sqldf包,因为您似乎对 sql 很满意

library(sqldf)

sqldf("SELECT   arcs.*, from_node.node_label, to_node.node_label
       FROM  arcs
       JOIN nodes AS from_node 
            ON arcs.from_node_id = from_node.node_id
       JOIN nodes AS to_node 
            ON arcs.to_node_id = to_node.node_id;")

 arc_id from_node_id to_node_id node_label node_label
1      1            1          2          a          a
2      2            2          3          a          b
于 2013-01-15T17:23:42.633 回答
2

我倾向于同意@agstudy。但是在基础 R 中,您只需merge分两步执行此操作:

foo = merge(arcs, nodes, by.x='from_node_id', by.y='node_id')
bar = merge(foo, nodes, by.x='to_node_id', by.y='node_id')

bar
#   to_node_id from_node_id arc_id node_label.x node_label.y
# 1          2            1      1            a            a
# 2          3            2      2            a            b

您可以相应地重命名。如果您使用该data.table包并使用键控 data.tables 执行此合并,它将非常快。

于 2013-01-15T17:24:21.900 回答