识别并绘制被NA包围的数据点

时间:2018-09-28 10:06:17

标签: r ggplot2 na

我正在使用ggplot2geom_line()制作大量时间序列的线图。该数据集具有大量缺失值,我通常很高兴没有在缺失段上绘制线,因为这看上去很尴尬。

我的问题是,没有绘制出被NA包围的单个非NA数据点(或序列的开始/结尾的点,另一侧的NA)。可能的解决方案是为所有观察值添加geom_point(),但这会使我的文件大小增加十倍,并使图更难以阅读。

因此,我只想标识那些未显示在geom_line()上的数据点,并仅为那些数据点添加。有一种简单的方法可以识别这些点吗?

我的数据当前为长格式,下面的MWE可以作为示例。我想确定第1行和第7行,以便可以绘制它们:

library(ggplot2)
set.seed(1)
dat <- data.frame(time=rep(1:5,2),country=rep(1:2,each=5),value=rnorm(10))
dat[c(2,6,8),3] <- NA
ggplot(dat) + geom_line(aes(time,value,group=country))

> dat
   time country      value
1     1       1 -0.6264538
2     2       1         NA
3     3       1 -0.8356286
4     4       1  1.5952808
5     5       1  0.3295078
6     1       2         NA
7     2       2  0.4874291
8     3       2         NA
9     4       2  0.5757814
10    5       2 -0.3053884

2 个答案:

答案 0 :(得分:1)

您可以使用zoo::rollapply函数创建一个新列,其值只能用NA来代替。然后,您可以简单地绘制这些点。例如:

library(zoo)
library(ggplot2)

foo <-  data.frame(time =c(1:11), value = c(1 ,NA, 3, 4, 5, NA, 2, NA, 4, 5, NA))

# Perform sliding window processing
val <- c(NA, NA, foo$value, NA, NA) # Add NA at the ends of vector
val <- rollapply(val, width = 3, FUN = function(x){
    if (all(is.na(x) == c(TRUE, FALSE, TRUE))){
        return(x[2])
    } else {
        return(NA)
    }
})

foo$val_clean <- val[c(-1, -length(val))] # Remove first and last values

foo$val_clean

ggplot(foo) + geom_line(aes(time, value)) + geom_point(aes(time, val_clean))

ggplot results

答案 1 :(得分:0)

你的意思是这样吗?

library(tidyverse)
dat %>%
    na.omit() %>%
    ggplot() +
    geom_line(aes(time, value, group = country))

enter image description here