Как создать диаграмму Санки с помощью networkD3, если исходный и целевой узлы имеют одинаковые имена - PullRequest
0 голосов
/ 31 марта 2020

Я пытаюсь построить диаграмму Санки, используя пакет в .

Я думаю, что правильно настроил набор данных, начиная со таблицы. Вот мой код:

M <- data.frame(as.matrix( table(as.character(df$q4.1),as.character(df$q4.2))))

M <- filter(M, Freq !=0)

q4.1 и q4.2 - это две категориальные переменные с одинаковыми категориями. Мне интересно визуализировать потоки, идущие от ответов в q4.1 до q4.2.

nodes <- data.frame(
  name=c(as.character(M$Var1), as.character(M$Var2)) %>% unique()
)

Проблема в том, что, учитывая, что две переменные имеют одинаковые имена, когда я создать узлы, он включает в себя только один набор «имен».

Поэтому, если кто-то выбрал одну и ту же опцию в обоих вопросах, он в итоге получит один и тот же источник и цель (см. пример ниже)

M$IDsource <- match(M$Var1, nodes$name)-1 

M$IDtarget <- match(M$Var2, nodes$name)-1

M

Var1             Var2 Freq IDsource IDtarget

No idea      No idea   16        7        7

Как вы можете себе представить, результирующий график выглядит странно, поскольку люди, предоставляющие одинаковые ответы на оба вопроса, отображаются в виде круга, возвращающегося к одному и тому же источнику.

Переименовывает категории во втором вопросе единственная возможность решить проблему? Или что я делаю не так?

Спасибо за поддержку!

PS Я уже использовал пакет ggalluvial в ggplot2 для создания нужного мне графика. Однако он не так хорош (и может быть экспортирован как htmlwidget), как график, который вы можете получить с помощью пакета networkD3, поэтому я бы хотел воссоздать тот же график с networkD3. Вот успешный код, который я использовал с пакетом ggalluvial.

ggplot(data= M, aes(axis1= Var1, axis2= Var2, y= Freq)) + scale_x_discrete(limits = c("Next 6 months", "Next 12-18 Months"), expand=c(0.1, 0.05)) + geom_alluvium() + geom_stratum() + geom_text(stat="stratum", infer.label = TRUE)

1 Ответ

1 голос
/ 31 марта 2020

В networkD3::sankeyNetwork индекс (номер строки) фрейма данных узла является ключом между ссылками и фреймом данных узла, а не «именем». Таким образом, вы можете иметь несколько одинаковых имен во фрейме данных узлов, но если они предназначены для идентификации разных узлов, они должны быть в отдельных строках.

Например, если у вас есть данные, которые выглядят примерно так это ...

library(networkD3)
library(dplyr)

M <- expand.grid(Var1 = LETTERS[1:4], 
                 Var2 = LETTERS[1:4], 
                 stringsAsFactors = F)

M$Freq <- sample(1:100, nrow(M))

M
#>    Var1 Var2 Freq
#> 1     A    A   81
#> 2     B    A   84
#> 3     C    A   42
#> 4     D    A   71
#> 5     A    B    9
#> 6     B    B   79
#> 7     C    B   82
#> 8     D    B   76
#> 9     A    C   41
#> 10    B    C   63
#> 11    C    C   95
#> 12    D    C   61
#> 13    A    D   33
#> 14    B    D    2
#> 15    C    D   13
#> 16    D    D   38

добавить некоторый идентификатор к значениям, чтобы вы могли различить guish из какого они вопроса, например ...

M$Var1 <- paste0(M$Var1, '_q41')
M$Var2 <- paste0(M$Var2, '_q42')

M
#>     Var1  Var2 Freq
#> 1  A_q41 A_q42    9
#> 2  B_q41 A_q42   86
#> 3  C_q41 A_q42   62
#> 4  D_q41 A_q42   26
#> 5  A_q41 B_q42   44
#> 6  B_q41 B_q42   93
#> 7  C_q41 B_q42   36
#> 8  D_q41 B_q42   51
#> 9  A_q41 C_q42    6
#> 10 B_q41 C_q42    5
#> 11 C_q41 C_q42   21
#> 12 D_q41 C_q42   83
#> 13 A_q41 D_q42   40
#> 14 B_q41 D_q42   77
#> 15 C_q41 D_q42   20
#> 16 D_q41 D_q42   85

сделать то же самое, что вы сделали, чтобы получить уникальный список узлов, а затем сопоставить фрейм данных ссылок с ними ...

nodes <- data.frame(
  name=c(as.character(M$Var1), as.character(M$Var2)) %>% unique()
)

M$IDsource <- match(M$Var1, nodes$name)-1

M$IDtarget <- match(M$Var2, nodes$name)-1

nodes
#>    name
#> 1 A_q41
#> 2 B_q41
#> 3 C_q41
#> 4 D_q41
#> 5 A_q42
#> 6 B_q42
#> 7 C_q42
#> 8 D_q42

M
#>     Var1  Var2 Freq IDsource IDtarget
#> 1  A_q41 A_q42    9        0        4
#> 2  B_q41 A_q42   86        1        4
#> 3  C_q41 A_q42   62        2        4
#> 4  D_q41 A_q42   26        3        4
#> 5  A_q41 B_q42   44        0        5
#> 6  B_q41 B_q42   93        1        5
#> 7  C_q41 B_q42   36        2        5
#> 8  D_q41 B_q42   51        3        5
#> 9  A_q41 C_q42    6        0        6
#> 10 B_q41 C_q42    5        1        6
#> 11 C_q41 C_q42   21        2        6
#> 12 D_q41 C_q42   83        3        6
#> 13 A_q41 D_q42   40        0        7
#> 14 B_q41 D_q42   77        1        7
#> 15 C_q41 D_q42   20        2        7
#> 16 D_q41 D_q42   85        3        7

, если вы не хотите, чтобы суффикс вопроса был виден в вывод Sankey, вы можете удалить его, если вы уже сопоставили правильный индекс ...

nodes$name <- sub('_q4[1-2]$', '', nodes$name)

, а затем напечатаете ...

sankeyNetwork(M, nodes, 'IDsource', 'IDtarget', 'Freq', 'name')

...