8

次のデータ フレームを検討してください。

   Country     Provinces          City Zone
1   Canada   Newfondland      St Johns    A
2   Canada           PEI Charlottetown    B
3   Canada   Nova Scotia       Halifax    C
4   Canada New Brunswick   Fredericton    D
5   Canada        Quebec            NA   NA
6   Canada        Quebec   Quebec City   NA
7   Canada       Ontario       Toronto    A
8   Canada       Ontario        Ottawa    B
9   Canada      Manitoba      Winnipeg    C
10  Canada  Saskatchewan        Regina    D

次の形式で(パッケージtreeNetworkから)互換性のあるリストに変換する賢い方法はありますか?networkD3

CanadaPC <- list(name = "Canada",
                 children = list(
                   list(name = "Newfoundland",
                        children = list(list(name = "St. John's",
                                             children = list(list(name = "A"))))),
                   list(name = "PEI",
                        children = list(list(name = "Charlottetown",
                                             children = list(list(name = "B"))))),
                   list(name = "Nova Scotia",
                        children = list(list(name = "Halifax",
                                             children = list(list(name = "C"))))),
                   list(name = "New Brunswick",
                        children = list(list(name = "Fredericton",
                                             children = list(list(name = "D"))))),
                   list(name = "Quebec",
                        children = list(list(name = "Quebec City"))),
                   list(name = "Ontario",
                        children = list(list(name = "Toronto",
                                             children = list(list(name = "A"))),
                                        list(name = "Ottawa",
                                             children = list(list(name = "B"))))),
                   list(name = "Manitoba",
                        children = list(list(name = "Winnipeg",
                                             children = list(list(name = "C"))))),
                   list(name = "Saskatchewan",
                        children = list(list(name = "Regina",
                                             children = list(list(name = "D")))))))

任意のレベル セットを持つReingold-Tilfordツリーをプロットするには、次のようにします。

ここに画像の説明を入力

乱雑なループの組み合わせなど、最適ではないルーチンをいくつか試しforましたが、目的の形式でこれを取得できません。

理想的には、最初の列を (開始点) と見なすために関数がスケーリングされroot、他の列は異なるレベルの子となります。


編集

同じトピックで同様の質問があり、@MrFlick は興味深い再帰関数を提供しました。元のデータ フレームには固定レベルのセットがありました。NA@MrFlickの初期ソリューションでは対処されていない別のレベルの複雑さ(レベルの任意のセット)を追加するために sを導入しました。


データ

structure(list(Country = c("Canada", "Canada", "Canada", "Canada", 
"Canada", "Canada", "Canada", "Canada", "Canada", "Canada"), 
    Provinces = c("Newfondland", "PEI", "Nova Scotia", "New Brunswick", 
    "Quebec", "Quebec", "Ontario", "Ontario", "Manitoba", "Saskatchewan"
    ), City = c("St Johns", "Charlottetown", "Halifax", "Fredericton", 
    NA, "Quebec City", "Toronto", "Ottawa", "Winnipeg", "Regina"
    ), Zone = c("A", "B", "C", "D", NA, NA, "A", "B", "C", 
    "D")), class = "data.frame", row.names = c(NA, -10L), .Names = c("Country", 
"Provinces", "City", "Zone"))
4

1 に答える 1

7

このシナリオのより良い戦略は、再帰的かもしれません。これはsplit()そのような実装です。まず、サンプルデータはこちら

dd<-structure(list(Country = c("Canada", "Canada", "Canada", "Canada", 
"Canada", "Canada", "Canada", "Canada", "Canada", "Canada"), 
    Provinces = c("Newfondland", "PEI", "Nova Scotia", "New Brunswick", 
    "Quebec", "Quebec", "Ontario", "Ontario", "Manitoba", "Saskatchewan"
    ), City = c("St Johns", "Charlottetown", "Halifax", "Fredericton", 
    NA, "Quebec City", "Toronto", "Ottawa", "Winnipeg", "Regina"
    ), Zone = c("A", "B", "C", "D", NA, NA, "A", "B", "C", 
    "D")), class = "data.frame", row.names = c(NA, -10L), .Names = c("Country", 
"Provinces", "City", "Zone"))

"NA"文字列を真のNA値に置き換えたことに注意してください。さて、関数

rsplit <- function(x) {
    x <- x[!is.na(x[,1]),,drop=FALSE]
    if(nrow(x)==0) return(NULL)
    if(ncol(x)==1) return(lapply(x[,1], function(v) list(name=v)))
    s <- split(x[,-1, drop=FALSE], x[,1])
    unname(mapply(function(v,n) {if(!is.null(v)) list(name=n, children=v) else list(name=n)}, lapply(s, rsplit), names(s), SIMPLIFY=FALSE))
}

次に、実行できます

rsplit(dd)

テストデータで動作するようです。唯一の違いは、子ノードが配置される順序です。

于 2015-06-10T04:49:17.670 に答える