桑基图,其中节点之间的边对应于 N3 列
Sankey plot where edges between nodes correspond to an N3 column
我想根据下面生成的数据结构绘制桑基图,其中节点之间的边对应于 N3
列,它们的存在和厚度取决于 Value
列。对于下面的虚拟数据,绘图看起来像 this(但边缘厚度对应于 Value
列中的值)。我还没有看到任何像这样构建的桑基地块的例子。我使用 riverplot 包尝试了不同的选项,但由于它似乎无法处理 N3
列,因此它删除了所有重复项,例如 A 和 C 之间的边。
set.seed(123)
mat <- matrix(rbinom(20,100,0.01),4,5,dimnames=list(LETTERS[1:4],letters[1:5]))
mat
# a b c d e
# A 0 3 1 1 0
# B 2 0 1 1 0
# C 1 1 3 0 0
# D 2 2 1 2 3
rowKey <- c("A"="N1","B"="N1","C"="N2","D"="N2")
edges = expand.grid(c(split(names(rowKey), rowKey), list(N3 = colnames(mat))))
edges2 = sapply(1:nrow(edges), function(i)
mat[row.names(mat) == edges$N1[i] | row.names(mat) == edges$N2[i],
colnames(mat) == edges$N3[i]])
edges$Value = colSums(edges2) * (colSums(edges2 > 0) == nrow(edges2))
edges
# N1 N2 N3 Value
#1 A C a 0
#2 B C a 3
#3 A D a 0
#4 B D a 4
#5 A C b 4
#6 B C b 0
#7 A D b 5
#8 B D b 0
#9 A C c 4
#10 B C c 4
#11 A D c 2
#12 B D c 2
#13 A C d 0
#14 B C d 0
#15 A D d 3
#16 B D d 3
#17 A C e 0
#18 B C e 0
#19 A D e 0
#20 B D e 0
# Plotting a sankey plot using the riverplot package
require(riverplot)
require(RColorBrewer)
nodes = data.frame(ID = unique(c(as.character(edges$N1),
as.character(edges$N2))), stringsAsFactors = FALSE)
nodes$x <- c(rep(1,2),rep(2,2))
nodes$y <- c(0:1,0:1)
palette = paste0(brewer.pal(3, "Set1"), "60")
styles = lapply(nodes$y, function(n) {
list(col = palette[n+1], lty = 0, textcol = "black")
})
names(styles) = nodes$ID
rp <- list(nodes=nodes, edges=edges[,-3], styles=styles)
class(rp) <- c(class(rp), "riverplot")
plot(rp, plot_area = 0.95, yscale=0.06, srt=0)
# Warning message:
# In checkedges(x2$edges, names(x2)) :
# duplicated edge information, removing 16 edges
这是一个使用 ggforce 包
中的geom_parallel_sets()
的解决方案
devtools::install_github('thomasp85/ggforce')
edges1 <- gather_set_data(edges, 1:2)
ggplot(edges1, aes(x, id = id, split = y, value = Value)) +
geom_parallel_sets(aes(fill = N3), alpha = 0.3, axis.width = 0.1) +
geom_parallel_sets_axes(axis.width = 0.1) +
geom_parallel_sets_labels(colour = 'white')
我想根据下面生成的数据结构绘制桑基图,其中节点之间的边对应于 N3
列,它们的存在和厚度取决于 Value
列。对于下面的虚拟数据,绘图看起来像 this(但边缘厚度对应于 Value
列中的值)。我还没有看到任何像这样构建的桑基地块的例子。我使用 riverplot 包尝试了不同的选项,但由于它似乎无法处理 N3
列,因此它删除了所有重复项,例如 A 和 C 之间的边。
set.seed(123)
mat <- matrix(rbinom(20,100,0.01),4,5,dimnames=list(LETTERS[1:4],letters[1:5]))
mat
# a b c d e
# A 0 3 1 1 0
# B 2 0 1 1 0
# C 1 1 3 0 0
# D 2 2 1 2 3
rowKey <- c("A"="N1","B"="N1","C"="N2","D"="N2")
edges = expand.grid(c(split(names(rowKey), rowKey), list(N3 = colnames(mat))))
edges2 = sapply(1:nrow(edges), function(i)
mat[row.names(mat) == edges$N1[i] | row.names(mat) == edges$N2[i],
colnames(mat) == edges$N3[i]])
edges$Value = colSums(edges2) * (colSums(edges2 > 0) == nrow(edges2))
edges
# N1 N2 N3 Value
#1 A C a 0
#2 B C a 3
#3 A D a 0
#4 B D a 4
#5 A C b 4
#6 B C b 0
#7 A D b 5
#8 B D b 0
#9 A C c 4
#10 B C c 4
#11 A D c 2
#12 B D c 2
#13 A C d 0
#14 B C d 0
#15 A D d 3
#16 B D d 3
#17 A C e 0
#18 B C e 0
#19 A D e 0
#20 B D e 0
# Plotting a sankey plot using the riverplot package
require(riverplot)
require(RColorBrewer)
nodes = data.frame(ID = unique(c(as.character(edges$N1),
as.character(edges$N2))), stringsAsFactors = FALSE)
nodes$x <- c(rep(1,2),rep(2,2))
nodes$y <- c(0:1,0:1)
palette = paste0(brewer.pal(3, "Set1"), "60")
styles = lapply(nodes$y, function(n) {
list(col = palette[n+1], lty = 0, textcol = "black")
})
names(styles) = nodes$ID
rp <- list(nodes=nodes, edges=edges[,-3], styles=styles)
class(rp) <- c(class(rp), "riverplot")
plot(rp, plot_area = 0.95, yscale=0.06, srt=0)
# Warning message:
# In checkedges(x2$edges, names(x2)) :
# duplicated edge information, removing 16 edges
这是一个使用 ggforce 包
中的geom_parallel_sets()
的解决方案
devtools::install_github('thomasp85/ggforce')
edges1 <- gather_set_data(edges, 1:2)
ggplot(edges1, aes(x, id = id, split = y, value = Value)) +
geom_parallel_sets(aes(fill = N3), alpha = 0.3, axis.width = 0.1) +
geom_parallel_sets_axes(axis.width = 0.1) +
geom_parallel_sets_labels(colour = 'white')