我有两个数据集,显示了 3 个不同时间段内各地区之间的人员流动,其中中间时间段 (t2) 是各个时间段之间的唯一链接。现在我想使用 ggplot2 在 r 中绘制冲积图。下面的代码可以工作,但会产生一个丑陋的图,因为流量没有正确地来自节点(由于缺乏更好的单词)。理想情况下,可以这么说,流量将从节点进入的同一级别开始。我如何重新格式化数据才能实现这一点?在当前示例中,“D”是所需大小的两倍。
library(dplyr)
library(ggalluvial)
library(tidyr)
data_1 <- tibble(t1 = c("A", "B", "B","C"),
t2 = c("D", "E", "F", "G"),
value = c(99, 50, 50, 100))
data_2 <- tibble(t2 = c("D", "E", "F", "G"),
t3 = c("H", "H", "I", "J"),
value = c(100, 100, 80, 100))
data_1_long <- data_1 %>%
mutate(flow = 1:n()) %>%
pivot_longer(-c(flow, value), names_to = "time", values_to = "district")
data_2_long <- data_2 %>%
mutate(flow = (max(data_1_long$flow)+1):(max(data_1_long$flow)+nrow(data_2))) %>%
pivot_longer(-c(flow, value), names_to = "time", values_to = "district")
data_long <- bind_rows(data_1_long,
data_2_long)
plot_alluvial <-ggplot(data = data_long ,
aes(x = time,
stratum = district,
alluvium = flow,
y = value ,
label = district)) +
geom_flow(stat = "alluvium", lode.guidance = "backfront",
color = "darkgray") +
geom_stratum() +
geom_text(stat = "stratum") +
theme(legend.position = "bottom")
plot_alluvial
我认为问题在于您的数据并不真正适合冲积图,它显示了“固定”数量的实体如何切换类别。进入某个类别和离开该类别的人数是可变的。换句话说,t2 输入的大小与输出的大小不同。例如,“E”有 50 个进去,但有 100 个出去。 在这种情况下,使用加权方向图可能会更好:
library(igraph)
library(tidygraph)
library(ggraph)
data_1 <- tibble(t1 = c("A", "B", "B","C"),
t2 = c("D", "E", "F", "G"),
value = c(99, 50, 50, 100))
data_2 <- tibble(t2 = c("D", "E", "F", "G"),
t3 = c("H", "H", "I", "J"),
value = c(100, 100, 80, 100))
cbind(setNames(data_1, c('from', 'to', 'weight')), time = 't1-t2') |>
rbind(cbind(setNames(data_2, c('from', 'to', 'weight')), time = 't2-t3')) |>
igraph::graph.data.frame() |>
as_tbl_graph() |>
mutate(y = c(1:3, seq(0.5, 3.5, 1), 1:3),
x = c(0, 0, 0, 2, 2, 2, 2, 4, 4, 4)) |>
ggraph(layout = 'manual', x = x, y = y) +
geom_edge_diagonal(aes(width = weight/10), alpha = 0.2, flipped = TRUE) +
geom_node_circle(aes(r = 0.2), fill = 'white') +
geom_node_circle(aes(r = 0.2, fill = name), alpha = 0.5) +
geom_node_text(aes(label = name), size = 6) +
scale_edge_width_identity() +
annotate('text', x = c(0, 2, 4), y = 4, label = c('t1', 't2', 't3'),
size = 6) +
coord_equal() +
theme_void() +
theme(legend.position = 'none')