2016-07-01 13 views
0

NetworkD3パッケージを使用して2層Sankey Networksをうまくプロットしました。私は、ソース、ターゲット、および値の列のデータフレームを取り、Sankeyプロットを出力する関数を作成しました。私はこの機能を使って、同様のプロットをすばやく作成するのに役立ちます。私の質問は、機能の効率性に関するものではありません。おそらく私の問題の原因はそれにあります。多層SankeyNetwork(NetworkD3)はプロットしませんR

以下は再現可能な例を示します。私の関数が2つのデータセット(z1 & z2)のSankeyNetworkをどのように生成するかを示します。しかし、これらのデータセットを3層のSankeyNetworkを作成するというアイデアと組み合わせると、ビューアに何も表示されません(また、幅と高さを増やそうとしました)。私はこれがインデックス作成と関係があるかもしれないと推測していますが、過去にはインデックスをゼロにする必要があるというエラー出力が出ました。私は間違いなく、ただの空白のプロットを受け取ります。

library(networkD3) 
library(dplyr) 


# The function used to create the plots 
sanktify <- function(x) { 

    # Create nodes DF with the unique sources & targets from input 
    nodes <- unique(data.frame(c(unique(x$source), unique(x$target)))) 
    nodes$ID <- as.numeric(rownames(nodes)) - 1 # sankeyNetwork requires IDs to be zero-indexed 
    names(nodes) <- c("name", "ID") 

    # Create two versions of nodes for merging 
    nodes_source <- nodes 
    nodes_target <- nodes 

    names(nodes_source) <- c("source", "source_ID") 
    names(nodes_target) <- c("target", "target_ID") 

    # Replace source & target in links DF with IDs 
    links <- merge(x, nodes_source, by="source", all.x=TRUE) %>% 
    merge(nodes_target, by="target", all.x=TRUE) %>% 
    select(source_ID, target_ID, value) %>% 
    arrange(source_ID) 

    # Create Sankey Plot 
    sank <- sankeyNetwork(
    Links = links, 
    Nodes = nodes, 
    Source = "source_ID", 
    Target = "target_ID", 
    Value = "value", 
    NodeID = "name", 
    units = "USD", 
    fontSize = 12, 
    nodeWidth = 30 
) 

    return(sank) 

} 


# Creating & plotting first data frame. 
z1 <- tbl_df(data.frame(source = c("A", "A", "B", "B"), 
         target = c("Cardiovascular", "Neurological", "Cardiovascular", "Neurological"), 
         value = c(5, 8, 2, 10))) 

z1$source <- as.character(z1$source) 
z1$target <- as.character(z1$target) 
sanktify(z1) # Correctly produces plot 


# Creating & plotting 2nd data frame 
z2 <- tbl_df(data.frame(source = c("Cardiovascular", "Cardiovascular", "Neurological", "Neurological"), 
         target = c("IP Surg", "IP Med", "IP Surg", "IP Med"), 
         value = c(3, 7, 6, 1))) 

z2$source <- as.character(z2$source) 
z2$target <- as.character(z2$target) 
sanktify(z2) # Correctly produces plot 

# Combining the two dataframes into a new DF with the goal of creating a '3-layer' plot. 
z3 <- rbind(z1, z2) 
sanktify(z3) # Blank output. No errors in the R console 

答えて

1

回答は、投稿されたGithubの問題https://github.com/christophergandrud/networkD3/issues/134にあるはずです。ここでコードをコピーして貼り付けます。 uniqueは間違った場所にあり、ソースとターゲットの連結後に実行する必要があります。

library(networkD3) 
library(dplyr) 


# The function used to create the plots 
sanktify <- function(x) { 

    # Create nodes DF with the unique sources & targets from input 

    # ***** changing this is the key*********************************************************** 
    nodes <- data.frame(unique(c(x$source,x$target)),stringsAsFactors=FALSE) 
    # ************************************************************************************************ 
    nodes$ID <- as.numeric(rownames(nodes)) - 1 # sankeyNetwork requires IDs to be zero-indexed 
    names(nodes) <- c("name", "ID") 

    # use dplyr join over merge since much better; in this case not big enough to matter 
    # Replace source & target in links DF with IDs 
    links <- inner_join(x, nodes, by = c("source"="name")) %>% 
    rename(source_ID = ID) %>% 
    inner_join(nodes, by = c("target"="name")) %>% 
    rename(target_ID = ID) 

    # Create Sankey Plot 
    sank <- sankeyNetwork(
    Links = links, 
    Nodes = nodes, 
    Source = "source_ID", 
    Target = "target_ID", 
    Value = "value", 
    NodeID = "name", 
    units = "USD", 
    fontSize = 12, 
    nodeWidth = 30 
) 

    return(sank) 

} 



# use data_frame to avoid tbl_df(data.frame(
z1 <- data_frame(
    source = c("A", "A", "B", "B"), 
    target = c("Cardiovascular", "Neurological", "Cardiovascular", "Neurological"), 
    value = c(5, 8, 2, 10) 
) 
z2 <- data_frame(
    source = c("Cardiovascular", "Cardiovascular", "Neurological", "Neurological"), 
    target = c("IP Surg", "IP Med", "IP Surg", "IP Med"), 
    value = c(3, 7, 6, 1) 
) 

z3 <- bind_rows(z1,z2) 
sanktify(z3) 
0

問題を根絶するために面倒なステップバイステップの多くの仕事をやっているにもかかわらず、私は2つのデータフレームをrbind順序を逆にしようとしたんまごついありません。

z3 < - rbind(z2、z1)はSanktify関数で動作しますが、z3 < - rbind(z1、z2)は空白のプロットを生成します。

私の関数はゼロインデックス付きID#を提供するように設計されている理由はわかりません。ですから、JS/D3をよく理解している人なら、私は興味があります。

関連する問題