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

时间:2015-02-03 04:13:38

标签: r ggplot2

我使用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))

Plot with linerange

此图的要点是显示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)

Plot with thick lines that are fake rectangles

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

但是,geom_rect要求数据包含x的最小值和最大值,这意味着我需要重新构造actual以查找类似的内容:

xmin xmax colour
   0    1    red
   1    5   blue

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

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

1 个答案:

答案 0 :(得分:0)

感谢@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)))

Plot with actual rectangles