计算NA之间的行数

时间:2014-11-05 16:12:32

标签: r

我试图从之前创建的结果集中获取特定计数。我需要在包含NA' s的行之间计算行数。这些行的值的聚合不重要,只有计数。

下面是一个非常简单的例子,希望能更好地解释我在说什么。左边是实际数据,右边是所需结果。

+------+-------+---+------+--------+
| TIME | Value | - | TIME | Result |
+------+-------+---+------+--------+
|   10 | NA    | - |   20 |      2 |
|   20 | 0     | - |   60 |      3 |
|   30 | 1     | - |      |        |
|   40 | NA    | - |      |        |
|   50 | NA    | - |      |        |
|   60 | 30    | - |      |        |
|   70 | 68    | - |      |        |
|   80 | 0     | - |      |        |
|   90 | NA    | - |      |        |
+------+-------+---+------+--------+

欢迎任何评论。如果需要额外输入,请留言。

4 个答案:

答案 0 :(得分:6)

为了使我的答案在这里完成修改版本:

d <- data.frame( TIME = seq(10, 90, by = 10), Value = c(NA, 0, 1, NA, NA, 30, 68, 0, NA))


aux <- rle(as.numeric((!is.na(d[,2]))))

cbind(TIME = d[cumsum(aux$lengths)[which(aux$values == 1)] - aux$lengths[aux$values == 1] +1, 1],
Result = rle(is.na(d$Value))$lengths[!rle(is.na(d$Value))$values])
     TIME Result
[1,]    2     20
[2,]    3     60

答案 1 :(得分:6)

rle外,您还可以使用diffwhichis.na的组合:

dat <- data.frame(time = seq(10, 90, 10), value = c(NA, 0, 1, NA, NA, 30, 68, 0, NA))
res <- data.frame(result = diff(which(is.na(dat$value))) - 1)
res$time <- dat$time[which(is.na(dat$value)) + 1][1:nrow(res)]
res[res$result != 0, ]
# time result
#   20      2
#   60      3

答案 2 :(得分:5)

我的"SOfun" packagea function called TrueSeq,就像一个带有逻辑向量的群组制作者。您可以将该函数与“data.table”结合使用以获得所需的结果,如下所示:

library(SOfun)
library(data.table)
na.omit(data.table(TIME = df$TIME, Val = TrueSeq(
  !is.na(df$value), zero2NA = TRUE)))[, list(TIME = TIME[1], .N), by = Val]
#    Val TIME N
# 1:   1   20 2
# 2:   2   60 3

如果您安装了“devtools”,则可以使用以下命令安装“SOfun”

library(devtools)
install_github("mrdwab/SOfun")

作为参考,I've posted this Gist能够在此答案中比较不同方法的结果。

总结:

  • 如果“值”列中的第一个值为NA
    • 所有方法都会产生相同的答案。
  • 如果“值”列中的第一个值不是NA
    • 这个答案和@ RStudent是相同的,从第一个NA值开始(因此,输入的第一行)作为结果的第一行。
    • @ konvas的回答和@ beginneR是一样的,从第二个NA值开始,作为结果的第一行。

答案 3 :(得分:3)

这可能不是最直接的方法,但它确实产生了预期的结果,因为我写了它,我想我也可以发布它(使用@konvas的样本数据):

require(dplyr)

dat %>%
  group_by(m = cumsum(is.na(value))) %>% 
  summarise(n = n() -1, time = first(time[!is.na(value)])) %>%
  ungroup() %>%
  filter(n > 0 & m > 0) %>% 
  select(-m)
#Source: local data frame [2 x 2]
#
#  n time
#1 2   20
#2 3   60
编辑:为了回应Ananda的评论,我做了一个小小的修正,希望它现在更好用。 例如,如果数据是:

dat <- data.frame(time = seq(10, 90, 10), value = c(0, 2, 1, NA, NA, 30, 68, 0, NA))
dat
#  time value
#1   10     0
#2   20     2
#3   30     1
#4   40    NA
#5   50    NA
#6   60    30
#7   70    68
#8   80     0
#9   90    NA

代码会导致:

dat %>%
  group_by(m = cumsum(is.na(value))) %>% 
  summarise(n = n() -1, time = first(time[!is.na(value)])) %>%
  ungroup() %>%
  filter(n > 0 & m > 0) %>% 
  select(-m)
#Source: local data frame [1 x 2]
#
#  n time
#1 3   60