【问题标题】:R: find first non-NA observation in data.table column by groupR:按组在 data.table 列中查找第一个非 NA 观察值
【发布时间】:2016-06-09 10:53:33
【问题描述】:

我有一个 data.table 有许多缺失值,我想要一个变量,它给我一个 1 表示每组中的第一个非缺失值。

假设我有这样一个data.table:

library(data.table)
DT <- data.table(iris)[,.(Petal.Width,Species)]
DT[c(1:10,15,45:50,51:70,101:134),Petal.Width:=NA]

现在在开头、结尾和中间都有缺失。我试过两个版本,一个是:

DT[min(which(!is.na(Petal.Width))),first_available:=1,by=Species]

但它只找到全局最小值(在这种情况下,setosa 得到正确的 1),而不是组的最小值。我认为是这种情况,因为data.table 首先是 i 的子集,然后按组排序,对吗?所以它只适用于全局最小值 which(!is.na(Petal.Width)) 的行,这是第一个非 NA 值。

第二次尝试 j 中的测试:

DT[,first_available:= ifelse(min(which(!is.na(Petal.Width))),1,0),by=Species]

它只返回一列 1。在这里,我没有很好的解释为什么它不起作用。

我的目标是:

DT[,first_available:=0]
DT[c(11,71,135),first_available:=1]

但实际上我有数百个组。任何帮助将不胜感激!

编辑:this 问题确实很接近,但不是针对 NA 的,如果我理解正确,也不能解决这里的问题。我试过了:

DT <- data.table(DT, key = c('Species'))
DT[unique(DT[,key(DT), with = FALSE]), mult = 'first']

【问题讨论】:

标签: r data.table


【解决方案1】:

这是一种方法:

DT[!is.na(Petal.Width), first := as.integer(seq_len(.N) == 1L), by = Species]

【讨论】:

  • 很好,这个还保留了 NA 的中间部分,这可能很方便
  • 你好,很好,你能解释一下你的这部分代码吗seq_len(.N)
  • .N 是一个特殊符号,用于保存每个组的观察次数。而seq_len 构造了一个从 1 到 .N 的序列。请参阅?data.table 了解.N 和其他特殊符号,以及?seq_len 了解更多信息。
【解决方案2】:

我们可以试试

DT[DT[, .I[which.max(!is.na(Petal.Width))] , Species]$V1, 
     first_available := 1][is.na(first_available), first_available := 0]

或者更紧凑的选项是

DT[, first_available := as.integer(1:nrow(DT) %in% 
      DT[, .I[!is.na(Petal.Width)][1L], by = Species]$V1)][]

【讨论】:

  • 太棒了,这正是我想要的。我会赶上 .I 和 1L
【解决方案3】:
  > DT[!is.na(DT$Petal.Width) & DT$first_available == 1]
  #      Petal.Width    Species first_available
  #   1:         0.2     setosa               1
  #   2:         1.8 versicolor               1
  #   3:         1.4  virginica               1

  > rownames(DT)[!is.na(DT$Petal.Width) & DT$first_available == 1]
  # [1] "11"  "71"  "135"

  > rownames(DT)[!is.na(DT$Petal.Width) & DT$first_available == 0]
  # [1] "12"  "13"  "14"  "16"  "17"  "18"  "19"  "20"  "21"  "22"  "23"  "24" 
  # [13] "25"  "26"  "27"  "28"  "29"  "30"  "31"  "32"  "33"  "34"  "35"  "36" 
  # [25] "37"  "38"  "39"  "40"  "41"  "42"  "43"  "44"  "72"  "73"  "74"  "75" 
  # [37] "76"  "77"  "78"  "79"  "80"  "81"  "82"  "83"  "84"  "85"  "86"  "87" 
  # [49] "88"  "89"  "90"  "91"  "92"  "93"  "94"  "95"  "96"  "97"  "98"  "99" 
  # [61] "100" "136" "137" "138" "139" "140" "141" "142" "143" "144" "145" "146"
  # [73] "147" "148" "149" "150"

【讨论】:

  • 但这假设我已经有了答案,不是吗? first_available 是我想要得到的,我只是在最后手动构建它以显示我的目标。
  • 另外,混合data.tabledata.frame 语法不被认为是不好的风格吗?为了简单起见,我偶尔也会这样做,所以我不确定。你怎么看?
  • 糟糕,刚刚检查过了。我正在尝试您的 first_available,然后它在 DT 中,我的愚蠢。我正在通过数据框方式进行操作。稍后编辑我的答案。
猜你喜欢
  • 2014-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多