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

私が試したこと:

  • 次のように、これら 2 つのデータ フレームに直接アクセスしようとすると、多くの行列演算がループになります。

    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)
    
  • 最後に、次の 2 つの関数を使用して、データ フレームを非正規化された「ビュー」に展開し、完了したら折りたたみます。これに関する唯一の問題は、データフレームが「展開」されている間、影響を受ける列が変更されないことを手動で保証する必要があることです。

    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に変換できますが、SQLにsqldf慣れているように見えるので、パッケージを使用する方が簡単です

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 では、これを 2 つの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 に答える