计算变量的 运行 长度并使用 ggplot 绘图

Calculate the run length of a variable and plot with ggplot

我正在使用 ggplot 绘制由一个因子着色的有序数字序列。例如,给定这个假数据:

# Generate fake data
library(dplyr)
set.seed(12345)
plot.data <- data.frame(fitted = rnorm(20),
                        actual = sample(0:1, 20, replace=TRUE)) %>%
  arrange(fitted)

head(plot.data)
      fitted actual
1 -1.8179560      0
2 -0.9193220      1
3 -0.8863575      1
4 -0.7505320      1
5 -0.4534972      1
6 -0.3315776      0

我可以轻松地将第 1-20 行的 actual 列绘制为彩色线条:

# Plot with lines
ggplot(plot.data, aes(x=seq(length.out = length(actual)), colour=factor(actual))) +
  geom_linerange(aes(ymin=0, ymax=1))

此图的要点是显示 actual 数字在 fitted 值范围内按顺序出现的频率。正如您在图像中看到的,连续的 0 和 1 很容易被视为连续的蓝色和红色垂直线。

但是,我想远离线条并使用 geom_rect 来为序号创建带。我可以用非常粗的线范围来伪造它:

# Fake rectangular regions with thick lines
ggplot(plot.data, aes(x=seq(length.out = length(actual)), colour=factor(actual))) +
  geom_linerange(aes(ymin=0, ymax=1), size=10)

但是这些线的大小取决于观察的数量——如果它们太粗,它们就会重叠。此外,这样做意味着绘制了一堆无关的图形元素(即连续的矩形部分实际上只是一堆相互渗透的线段)。最好改用geom_rect

但是,geom_rect 要求数据包括 x 的最小值和最大值,这意味着我需要重塑 actual 以使其看起来像这样:

xmin xmax colour
   0    1    red
   1    5   blue

我需要以编程方式计算每种颜色的 运行 长度以标记该颜色的开始和结束。我知道 R 有 rle() 函数,这可能是计算 运行 长度的最佳选择,但我不确定如何将 运行 长度分成两列(xminxmax).

计算变量 运行 长度以便 geom_rect 可以正确绘制它的最佳方法是什么?

感谢@baptiste,解决这个问题的最佳方法似乎是将数据压缩到那些在 x 中看到变化的行:

condensed <- plot.data %>% 
  mutate(x = seq_along(actual), change = c(0, diff(actual))) %>% 
  subset(change != 0 ) %>% select(-change)

first.row <- plot.data[1,] %>% mutate(x = 0)

condensed.plot.data <- rbind(first.row, condensed) %>%
  mutate(xmax = lead(x),
         xmax = ifelse(is.na(xmax), max(x) + 1, xmax)) %>%
  rename(xmin = x)

condensed.plot.data
#       fitted actual xmin xmax
# 1 -1.8179560      0    0    2
# 2 -0.9193220      1    2    6
# 3 -0.3315776      0    6    9
# 4 -0.1162478      1    9   11
# 5  0.2987237      0   11   14
# 6  0.5855288      1   14   15
# 7  0.6058875      0   15   20
# 8  1.8173120      1   20   21

ggplot(condensed.plot.data) + 
  geom_rect(aes(xmin=xmin, xmax=xmax, ymin=0, ymax=1, fill=factor(actual)))