r:使用 ggvis 而不是 ggplot 创建瀑布图

r: Create waterfall chart with ggvis instead of ggplot

我用 ggplot 创建了下面的瀑布图,基于这个很好 post http://analyticstraining.com/2015/waterfall-charts-using-ggplot2-in-r/

现在我想在 ggvis 中创建这个图表。我知道有一个瀑布包可以创建这种情节,但我想在 ggvis 中使用它。 (这里有一个link给包https://www.r-bloggers.com/waterfall-plots-in-r/

我开始多次尝试使用 ggvis 创建图表,但现在我都失败了。我能做的最好的就是 layer_paths:

我试过使用 layer_bars,它似乎不适用于负值。我尝试使用 layer_rects,就像在 ggplot 中一样,但我无法为 ymin 等设置道具。

我对 ggvis 和 Vega Marks 的内部工作原理了解不是很深,有人可以告诉我如何成功吗?

这是带有示例数据的两个图的代码。

library(dplyr)
library(ggplot2)
library(ggvis)
library(lubridate)
library(tidyr)


test_data <- structure(list(id = 1:11,
                            process = c("Inventory", "Add_to_Storage", 
                                       "Remove_from_storage", "Remove_from_storage", "Remove_from_storage", "Remove_from_storage", 
                                       "Remove_from_storage", "Remove_from_storage", "Remove_from_storage", "Remove_from_storage", 
                                       "Remove_from_storage"), 
                            date = structure(c(16161,16161, 16161, 16161, 16161, 16161, 16161, 16161, 16161, 16161,16161), class = "Date"), 
                            timestamp = structure(1:11, .Label = c("00:00:01","10:04:00", "12:23:33", "12:43:23", "13:36:37", "19:08:27", "19:26:56", "19:49:41", "20:01:04", "20:02:27", "20:11:32"), class = "factor"), 
                            inv_yest = c(0,NA, NA, NA, NA, NA, NA, NA, NA, NA, NA),
                            inv_added = c(NA, 3, NA, NA, NA, NA, NA, NA, NA, NA, NA), 
                            inv_remove = c(NA, NA, 1, 1, 1, 1, 1, 1, 1, 1, 1), 
                            inv_change = c(0, 3, -1, -1, -1, -1, -1, -1, -1, -1, -1), 
                            inv_end = c(0,3, 2, 1, 0, -1, -2, -3, -4, -5, -6), 
                            inv_start = c(0, 0, 3, 2, 1, 0, -1, -2, -3, -4, -5)
                            ), 
                       .Names = c("id", "process","date", "timestamp", "inv_yest", "inv_added", "inv_remove","inv_change","inv_end", "inv_start"), 
                       row.names = c(NA, -11L), 
                       class = c("tbl_df", "tbl", "data.frame")
                       )

# Waterfall Plot with ggplot
ggplot(test_data,
       aes(x = timestamp,
           fill = process
           )
) +
  geom_rect(aes(x = timestamp,
                xmin = id - 0.45,
                xmax = id + 0.45,
                ymin = inv_end,
                ymax = inv_start
                )
  ) +
  geom_text(
    aes(
      x = timestamp,
      y = inv_end + 2,
      label = inv_change
    ),
    position = position_dodge(width = 1)
  ) +
  theme(axis.text.x=element_text(angle=90),
        axis.title.y=element_blank(),
        plot.title = element_text(
          lineheight=1.0,
          face="bold",
          hjust = 0.5
        ) 
  ) +
  ggtitle(paste0("Inventory development on day ",unique(test_data$date)))  # fügt Titel hinzu

# Add lower boundaries and only positive changes
test_data %>%
  dplyr::mutate(inv_lower = pmin(inv_start,inv_end)) %>%
  dplyr::mutate(inv_upper = ifelse(inv_change < 0,inv_change*(-1),inv_change)) -> test_data


# Test with ggplot geom_step
ggplot() +
  geom_step(data=test_data, mapping=aes(x=timestamp, y=inv_end,group = 1)) +
  geom_step(data=test_data, mapping=aes(x=timestamp, y=inv_end,group = 1), 
            direction="vh", linetype=1) +
  geom_point(data=test_data, mapping=aes(x=timestamp, y=inv_end), color="red") 

# Test with ggvis layer_paths
# geom_step = layer_paths + transform_step # http://ggvis.rstudio.com/layers.html
# 
test_data %>%
  ggvis(x=~timestamp,
        y=~inv_end
        ) %>%
  layer_paths(interpolate:="step-after"
              ) %>%
  layer_paths(interpolate:="step-before"
              ) %>%
  layer_points(fill:="red")

提前感谢您的帮助

在 ggvis 和 layer_rects 中,参数是 yy2 而不是 yminymax。我把 y2fill 放在矩形层而不是 ggvis.

矩形的宽度是使用 width 设置的,而不是通过 "id" 变量手动设置的。

将文本位置设置到中心需要一些工作,并且对 "timestamp" 使用 "xcenter" 并在 scale_nominal 中使用 padding 参数。

test_data %>%
    ggvis(x = ~timestamp, y = ~inv_end) %>%
    layer_rects(y2 = ~inv_start, width = band(),
              fill = ~process) %>%
    layer_text(x = prop("x", ~timestamp, scale = "xcenter"),
             y = ~inv_end + 2,
             text := ~inv_change) %>%
    scale_nominal("x", name = "xcenter", padding = .9)