gg_sankey

 

好像有好久没有更新了,一直想自己用ggplot2实现一下sankey图,就着手做了一下最简单的.

一般的sankey图长这样,左边一列,右边一列,中间的条带是左右两个状态之间的转变.

那么,首先我们就需要构建左右两边的bar,在每个柱的中间标注上所占的比例:

library(ggplot2)
color_list <- c("#f38181", "#fce38a", "#61c0bf", "#95e1d3")
bar_data <- data.frame(
  x = c(1, 1, 1, 11, 11,11,11),
  type = c("a", "b", "c", "a", "b", "c","d"),
  y = c(0.2, 0.3, 0.5, 0.1, 0.5, 0.2, 0.2)
)
text_data_create <- function(bar_data){
  x = bar_data$x
  text = bar_data$y
  y = apply(
    matrix(names(table(x)), ncol = 1),
    1,
    function(x_group){
      index = which(x == as.numeric(x_group))
      start = cumsum(text[index])
      end = c(0, start[1:(length(start)-1)])
      
      return((1-(start + end)/2))
    }
  )
  text_data =  data.frame(
    x = x,
    y = unlist(y), 
    text = text
  )
}
bar_p <- ggplot(data = bar_data) +
  geom_bar(position = "fill", stat = "identity", aes(fill = type, x,y), colour = "white", width = 0.8) +
  geom_text(data = text_data_create(bar_data), aes(x, y, label = text)) +
  scale_fill_manual(values = color_list) 

结果如图:

接下去就是中间引流线的构建,简单来说其实就是确定上线和下线,为了美观,我用 \(X^{3}\)给线加上弧度:

river_data_create <- function(start_y_upper, end_y_upper, start_y_lower, end_y_lower){
  x = seq((1 + 0.8/2), (11 - 0.8/2), length = 10000)
  mean_y_upper = (start_y_upper + end_y_upper)/2
  y_upper = (start_y_upper - mean_y_upper)/(4.6^3)*(-x + 6)^3 + mean_y_upper
  mean_y_lower = (start_y_lower + end_y_lower)/2
  y_lower = (start_y_lower - mean_y_lower)/(4.6^3)*(-x + 6)^3 + mean_y_lower
  river_data = data.frame(
    x,
    y_upper,
    y_lower
  )
  text_data = data.frame(
    x = 6,
    y = (start_y_upper + end_y_lower) / 2,
    text = as.character(start_y_upper - start_y_lower)
  )
  return(list(line = river_data, text = text_data))
}

这样就完成了计算导流线的点坐标,之后就利用 geom_ribbon 往图层上添加即可.

river_data <- river_data_create(1,0.9,0.9, 0.8)
sankey_p <- bar_p + 
  geom_ribbon(data = river_data$line, aes(x, ymin = y_lower, ymax = y_upper), fill = color_list[1], colour = "white", alpha = 0.2) +
  geom_text(data = river_data$text, aes(x,y,label = text))

river_data <- river_data_create(0.5,0.6, 0.4, 0.5)
sanky_p <- sanky_p + 
  geom_ribbon(data = river_data$line, aes(x, ymin = y_lower, ymax = y_upper), fill = color_list[3], colour = "white", alpha = 0.2) +
  geom_text(data = river_data$text, aes(x,y,label = text))

river_data <- river_data_create(0.2,0.2, 0, 0)
sanky_p <- sanky_p + 
  geom_ribbon(data = river_data$line, aes(x, ymin = y_lower, ymax = y_upper), fill = color_list[3], colour = "white", alpha = 0.2) +
  geom_text(data = river_data$text, aes(x,y,label = text))

最后就是对theme的调整,把一些没用的线去掉:

虽然现在已经有很多包可以实现 sankey 图的绘画, 比如 riverplot, 但是实现一次还是挺有意思的.

最后,祝您

身体健康.

转载于:https://www.cnblogs.com/wwdPeRl/p/11127051.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
项目:使用AngularJs编写的简单 益智游戏(附源代码)  这是一个简单的 javascript 项目。这是一个拼图游戏,也包含一个填字游戏。这个游戏玩起来很棒。有两个不同的版本可以玩这个游戏。你也可以玩填字游戏。 关于游戏 这款游戏的玩法很简单。如上所述,它包含拼图和填字游戏。您可以通过移动图像来玩滑动拼图。您还可以选择要在滑动面板中拥有的列数和网格数。 另一个是填字游戏。在这里你只需要找到浏览器左侧提到的那些单词。 要运行此游戏,您需要在系统上安装浏览器。下载并在代码编辑器中打开此项目。然后有一个 index.html 文件可供您修改。在命令提示符中运行该文件,或者您可以直接运行索引文件。使用 Google Chrome 或 FireFox 可获得更好的用户体验。此外,这是一款多人游戏,双方玩家都是人类。 这个游戏包含很多 JavaScript 验证。这个游戏很有趣,如果你能用一点 CSS 修改它,那就更好了。 总的来说,这个项目使用了很多 javascript 和 javascript 库。如果你可以添加一些具有不同颜色选项的级别,那么你一定可以利用其库来提高你的 javascript 技能。 演示: 该项目为国外大神项目,可以作为毕业设计的项目,也可以作为大作业项目,不用担心代码重复,设计重复等,如果需要对项目进行修改,需要具备一定基础知识。 注意:如果装有360等杀毒软件,可能会出现误报的情况,源码本身并无病毒,使用源码时可以关闭360,或者添加信任。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值