如何按类别查找(不替换)data.table列中的主要NA,间隙和最终NAs

时间:2018-03-22 10:33:44

标签: r data.table

我正试图了解我的面板数据集中的缺失类型。我认为可能有三种情况:

  1. 领导NA的;在为某个人开始数据之前
  2. 间隙;所以在数据重新启动之后的几个时间段内丢失了数据
  3. NA的结尾;如果一个人提早停止,数据
  4. 我不是在寻找直接改变它们或填充它们的函数。相反,我想在得知问题之后决定如何处理它们。

    如何摆脱领先的NA(但不知道如何查看你有多少)已经解决here。解决所有NA的问题非常简单:

    library(data.table)
    Data <- as.data.table(iris)[,.(Species,Petal.Length)]
    Data[, time := rep(1951:2000,3)]
    Data[c(1:5,60:65,145:150), Petal.Length := NA]
    # in Petal lenth setosa has lead NA's, versicolor a gap, virginica NA's at the end
    
    Data[is.na(Petal.Length)] # this is a mix of all three types of NA's 
    

    但我想区分这三种情况。理想情况下,我想直接在data.table中解决它们

    1. “给我一个数据表,其中包含在Petal.Length中具有领先NA的所有观察结果”
    2. “给我一个数据表,其中的观察结果是Petal.Length的差距”
    3. “给我一个数据表,其中包含每个人最后一段时间内NA的观察结果”
    4. 对于领导NA,我仍然可以完成它,但感觉超级笨拙:

      Data[!is.na(Petal.Length), firstobs := ifelse(min(time) == time, 1, 0), by = Species]
      Data[, mintime := max(firstobs * time, na.rm = T), by = Species]
      Data[time < mintime]
      

      我想类似的事情可以用max和最后一个NA的线索来完成,但是我无法理解差距,这对我来说是最重要的。我在网上找到的解决方案通常直接填写,删除或转移这些NA,我只是想看看。

      所需的输出将是:

      领导NAs:

      Data[1:5]
      

      间隙:

      Data[60:65]
      

      NA的结尾:

      Data[145:150]
      

      但是我想通过检查三种类型NA的位置来获取这些,因为我的实际数据集很大,需要手动检查。

      编辑:我应该在我的真实数据集中添加它,我不知道每个人何时开始报告数据。所以:

      Data[is.na(Petal.Length), time, by= Species]
      

      不会帮助我。

2 个答案:

答案 0 :(得分:1)

好像你可以在这里定义function作为帮助:

my.fun <- function(spe){
  k1 <- intersect(which(dat$Species == spe), which(is.na(dat$Petal.Length)))
  k2 <- intersect(which(dat$Species == spe), which(!is.na(dat$Petal.Length)))
  mintime <- min(dat$time[k2])
  mintime.na <- min(dat$time[k1])
  c <- (length(k1) > 0) && (mintime.na <= mintime)
  if(c){
    x <- cbind(dat[k1,], mintime)
    return(x)
    }
}
species.list <- as.character(unique(Data$Species))
sapply(species.list, my.fun)
# returns
$setosa
   Species Petal.Length time mintime
1:  setosa           NA 1951    1956
2:  setosa           NA 1952    1956
3:  setosa           NA 1953    1956
4:  setosa           NA 1954    1956
5:  setosa           NA 1955    1956

$versicolor
NULL

$virginica
NULL

虽然Petal.Length&#34;中存在所有差距,但我对你的意思仍然不清楚。

答案 1 :(得分:1)

一种方式:

Data[, g := {
  r = rleid(vna <- is.na(Petal.Length))
  if (first(vna)) r = replace(r, r == 1L, 0L)
  if ( last(vna)) r = replace(r, r == last(r), 9999L)
  replace(r, !vna, NA_integer_)
}, by=Species]

确认它与OP期望的行匹配...

> # leading
> Data[g == 0L, which = TRUE]
[1] 1 2 3 4 5
> # trailing
> Data[g == 9999L, which = TRUE]
[1] 145 146 147 148 149 150
> # gaps
> Data[!.(c(0L, 9999L, NA_integer_)), on="g", which = TRUE]
[1] 60 61 62 63 64 65

要获取子集,请使用不带which = TRUE参数的这些命令。

除了识别三个类别中的每一个行之外,如果有多个类别,此方法还会通过不同的g值来识别差距。

工作原理

您可以插入一些printcat指令,以了解每个对象在循环过程中的样子:

csprintf <- function(s, ...) cat(sprintf(s, ...))
Data[, g := {
  csprintf("Group: %s = %s %s\n", toString(names(.BY)), toString(.BY), strrep("*", 60))

  r = rleid(vna <- is.na(Petal.Length))
  csprintf("NA positions and initial grouping vector:\n")
  print(data.table(Petal.Length, r, vna))

  if (first(vna)) r = replace(r, r == 1L, 0L)
  csprintf("NA positions and grouping vector after tagging leading NAs:\n")
  print(data.table(Petal.Length, r, vna))

  if ( last(vna)) r = replace(r, r == last(r), 9999L)
  csprintf("NA positions and grouping vector after tagging trailing NAs:\n")
  print(data.table(Petal.Length, r, vna))

  r = replace(r, !vna, NA_integer_)
  csprintf("NA positions and grouping vector after tagging non-NAs:\n")
  print(data.table(Petal.Length, r, vna))

  cat(strrep("\n", 2))

  r
}, by=Species]

实际上,它创建了指示NA位置的vna向量和组在vna中运行的r向量。然后,它会为某些特定的运行分配特殊代码,以后可以用于过滤。