Я пытаюсь создать диаграмму Санки, по концепции похожую на ту, которую видели здесь . Диаграмма, которую я надеюсь создать, скорее всего, будет иметь больше промежуточных узлов, чем в приведенном примере.
Я пытался использовать пакет networkd3 , в частности, функцию sankeyNetwork
. Моя трудность состоит в том, чтобы получить данные, которые у меня есть, в правильную структуру для использования с sankeyNetwork
.
Мои данные - это данные опроса, в которых респондентов просят ранжировать показатели от наиболее важных до наименее важных. Например,
W X Y Z
[1,] "Rank 1" "Rank 2" "Rank 3" "Rank 4"
[2,] "Rank 2" "Rank 3" "Rank 1" "Rank 4"
[3,] "Rank 1" "Rank 2" "Rank 3" "Rank 4"
[4,] "Rank 1" "Rank 2" "Rank 4" "Rank 3"
, где W, X, Y & Z - метрики.
Чтобы создать санки, мне нужны данные в виде:
0 1 10
0 2 5
1 3 2
Первый столбец представляет начальный узел (нумерация начинается с 0). Второй столбец является конечным узлом. Третий столбец - это значение / вес ссылки, соединяющей узлы. Также будет вектор, содержащий имена узлов.
Моя конечная цель - создать санки (перемещаясь слева направо) по первым узлам столбца, представляющим метрики с их долей полученных голосов "Ранга 1". Столбец 2 снова будет содержать все метрики, кроме ссылок, представляющих долю голосов «Ранг 2» и т. Д., Пока в последнем столбце не будут указаны доли голосов за последнее место каждого полученного показателя c.
Я ищу способ автоматизировать преобразование данных (из-за отсутствия лучшего слова), так как набор данных, который у меня должен быть, будет иметь 7 метрик (таким образом, 7 позиций ранжирования) и ответы от 50-100 человек и Таким образом, существует множество возможных комбинаций рейтинга.
В данный момент я могу использовать что-то похожее на
example_data %>%
filter(W == "Rank 1" && X == "Rank 2") %>%
tally()
, чтобы предоставить счет, но для этого требуется, чтобы я записал его или через l oop, каждую возможную комбинацию метрик и рейтинги. На самом деле это неосуществимо для объема данных, с которыми я предлагаю работать.
Редактировать: Спасибо за отзыв CJ Yetman. Мне уже удалось решить проблему, и поэтому мне не нужно было реализовывать ваш ответ, но ваше решение потенциально немного проще, чем то, что я в итоге сделал.
Я создал набор данных sankey_data, содержащий исходные данные, чтобы Я хотел бы иметь копию данных для работы с.
sankey_data[["id"]] <- seq(1, nrow(sankey_data))
sankey_data <- sankey_data %>%
select(id, everything())
sankey_data <- apply(sankey_data, 2, as.character)
# Not necessarily required but I needed to convert the data points from factors
# to characters.
# Creating new variables to store data in more helpful format
sankey_data$Rank1 <- rep(NA, nrow(sankey_data))
sankey_data$Rank2 <- rep(NA, nrow(sankey_data))
sankey_data$Rank3 <- rep(NA, nrow(sankey_data))
sankey_data$Rank4 <- rep(NA, nrow(sankey_data))
# Filling in those new variables
ranking_levels <- c("Rank 1", "Rank 2", "Rank 3", "Rank 4")
for (i in 1:nrow(sankey_data)) {
for (j in 1:length(ranking_levels)) {
hold <- colnames(sankey_data[i, grep(sankey_data[i,],
pattern = paste0("^", ranking_levels[j]), fixed = F)])
sankey_data[i, 8 + j] <- hold
}
}
# Creating the Link data
Link1 <- sankey_data %>%
plyr::count(vars = c("Rank1", "Rank2")) %>%
mutate("link" = 1)
Link2 <- sankey_data %>%
plyr::count(vars = c("Rank2", "Rank3")) %>%
mutate("link" = 2)
Link3 <- sankey_data %>%
plyr::count(vars = c("Rank3", "Rank4")) %>%
mutate("link" = 3)
# I then added prefixes to each data point within links 1 - 3 respectively.
# I just used paste0 but won't include the detail here as this is additional to
# what is strictly necessary to create the Sankey.
# Adding column names
colnames(Link1) <- c("source", "target", "value", "link")
colnames(Link2) <- colnames(Link1)
colnames(Link3) <- colnames(Link1)
# Combing into a single data set
links <- rbind(Link1, Link2, Link3)
nodes <- data.frame(name = c(as.character(links[["source"]]),
as.character(links[["target"]])) %>% unique())
# As sankeyNetwork requires the nodes to be in numeric form (starting from 0),
# this serevs to convert the node names to numbers for input into the function
links[["IDsource"]] <- match(links[["source"]], nodes[["name"]]) - 1
links[["IDtarget"]] <- match(links[["target"]], nodes[["name"]]) - 1
# The Sankey
sankeyNetwork(Links = links,
Nodes = nodes,
Source = "IDsource",
Target = "IDtarget",
Value = "value",
fontFamily = "Arial",
NodeID = "name",
sinksRight = FALSE, fontSize = 24, height = 1400, width = 3200)
Этот код работал для меня. Я попытался адаптировать его для работы с данными примера, так как не могу опубликовать sh фактические данные, чтобы мог быть один или два артефакта, которые я пропустил и которые не имеют смысла. Просто дайте мне знать, если это так, и я постараюсь обновить его.