R ifelse条件:连续NA的频率

时间:2012-07-28 02:44:31

标签: r

我是R的新手,我正在寻找类似的问题,但未能找到一个修复我的问题,任何帮助都会受到赞赏。

我有一个数据框M:

            date value
1 182-2002-01-01 23.95
2 182-2002-01-02 17.47
3 182-2002-01-03  NA
4 183-2002-01-01  NA
5 183-2002-01-02  5.50
6 183-2002-01-03 17.02

我需要做的是:如果少于5个NA(连续),我将重复前一个数字(17.47),如果连续超过5个NA,我将需要删除整整一个月。

我多次尝试过功能,但是没有用,非常感谢你的帮助。

2 个答案:

答案 0 :(得分:2)

为了示范,我会稍微调整一下你的问题。 我将使用类似的数据集,但连续2个NAs。这很容易推广到5,不用担心。我还将使用更好地演示解决方案的数据集

首先,如何让您的数据看起来像我将要使用的那样:

library(reshape)
M2<-data.frame(colsplit(M$date, "-", c("ID", "year", "month", "day")), 
               value=M$value)

现在已经不在了,这是我将要使用的数据:

library(reshape)
M2<-data.frame(colsplit(M$date, "-", c("ID", "year", "month", "day")), 
               value=M$value)

set.seed(1234)
M2<-expand.grid(ID=182, year=2002:2004, month=1:2, day=1:3, KEEP.OUT.ATTRS=FALSE)
M2 <- M2[with(M2, order(year, month, day, ID)),] #sort the data
M2$value <- sample(c(NA, rnorm(100)), nrow(M2), 
                   prob=c(0.5, rep(0.5/100, 100)), replace=TRUE)
M2

    ID year month day      value
1  182 2002     1   1 -0.5012581
7  182 2002     1   2  1.1022975
13 182 2002     1   3         NA
4  182 2002     2   1 -0.1623095
10 182 2002     2   2  1.1022975
16 182 2002     2   3 -1.2519859
2  182 2003     1   1         NA
8  182 2003     1   2         NA
14 182 2003     1   3         NA
5  182 2003     2   1  0.9729168
11 182 2003     2   2  0.9594941
17 182 2003     2   3         NA
3  182 2004     1   1         NA
9  182 2004     1   2 -1.1088896
15 182 2004     1   3  0.9594941
6  182 2004     2   1 -0.4027320
12 182 2004     2   2 -0.0151383
18 182 2004     2   3 -1.0686427

首先,我们将删除所有在一个月内连续存在2个或更多NAs的案例:

NA_run <- function(x, maxlen){
  runs <- rle(is.na(x$value))
  if(any(runs$lengths[runs$values] >= maxlen)) NULL else x
  }

library(plyr)
rem <- ddply(M2, .(ID, year, month), NA_run, 2)
rem

    ID year month day      value
1  182 2002     1   1 -0.5012581
2  182 2002     1   2  1.1022975
3  182 2002     1   3         NA
4  182 2002     2   1 -0.1623095
5  182 2002     2   2  1.1022975
6  182 2002     2   3 -1.2519859
7  182 2003     2   1  0.9729168
8  182 2003     2   2  0.9594941
9  182 2003     2   3         NA
10 182 2004     1   1         NA
11 182 2004     1   2 -1.1088896
12 182 2004     1   3  0.9594941
13 182 2004     2   1 -0.4027320
14 182 2004     2   2 -0.0151383
15 182 2004     2   3 -1.0686427

你可以看到已经删除了两个NAs。剩下的那个是因为它属于两个不同的月份。现在我们要填写剩余的NA。如果NAs在开始时是正确的,那么na.rm=FALSE参数就是为了保留它们(我认为这是你想要的)。

library(zoo)
rem$value <- na.locf(rem$value, na.rm=FALSE)
rem

    ID year month day      value
1  182 2002     1   1 -0.5012581
2  182 2002     1   2  1.1022975
3  182 2002     1   3  1.1022975
4  182 2002     2   1 -0.1623095
5  182 2002     2   2  1.1022975
6  182 2002     2   3 -1.2519859
7  182 2003     2   1  0.9729168
8  182 2003     2   2  0.9594941
9  182 2003     2   3  0.9594941
10 182 2004     1   1  0.9594941
11 182 2004     1   2 -1.1088896
12 182 2004     1   3  0.9594941
13 182 2004     2   1 -0.4027320
14 182 2004     2   2 -0.0151383
15 182 2004     2   3 -1.0686427

现在,您需要做的就是将数据中的5个或更多内容更改为maxlenNA_run参数的值为5。

编辑:或者,如果您不希望从前几个月复制值:

library(zoo)
rem$value <- ddply(rem, .(ID, year, month), summarise, 
                   value=na.locf(value, na.rm=FALSE))$value
rem

    ID year month day      value
1  182 2002     1   1 -0.5012581
2  182 2002     1   2  1.1022975
3  182 2002     1   3  1.1022975
4  182 2002     2   1 -0.1623095
5  182 2002     2   2  1.1022975
6  182 2002     2   3 -1.2519859
7  182 2003     2   1  0.9729168
8  182 2003     2   2  0.9594941
9  182 2003     2   3  0.9594941
10 182 2004     1   1         NA
11 182 2004     1   2 -1.1088896
12 182 2004     1   3  0.9594941
13 182 2004     2   1 -0.4027320
14 182 2004     2   2 -0.0151383
15 182 2004     2   3 -1.0686427

答案 1 :(得分:0)

我分两步完成:

  1. 基于rlerollapplyshift的策略来填补小差距(连续少于5个NAs)。
  2. byaggregateddply为基础的策略,在步骤1之后剩余的NAs占用任意月份,并使整个月保持NA。