根据条件返回最大和最小索引

时间:2019-05-24 03:15:29

标签: r apply

我正在尝试编写一个函数,该函数将通过矩阵进行rowise处理并返回两个包含第一个和最后一个实例1的列号(x)的向量。但是,有一些条件。我的真实数据集是7,042行和841列。

  1. 如果在最后一列中找到1,则两个向量都返回ncols + 1
  2. 如果1从不出现,则两个向量都应== 1
  3. 如果1在行中多次出现,但仅被NA分隔,则返回最大列号+ 1
  4. 如果该行中多次出现1,但被任意0隔开,则返回最大和最小列号+ 1
  5. 如果1仅在行中出现一次,则返回列号+ 1

使用下面的示例数据集

structure(list(T1 = c(NA, NA, NA, 1L, NA, NA, NA, NA, NA), T2 = c(NA, 
NA, NA, 0L, NA, NA, NA, NA, NA), T3 = c(NA, 3L, 3L, 0L, 3L, NA, 
NA, 3L, 3L), T4 = c(NA, 4L, NA, 0L, 0L, NA, 4L, 0L, 4L), T5 = c(5L, 
5L, 5L, 0L, 0L, NA, 0L, 5L, 0L)), row.names = c(NA, -9L), class = "data.frame")


+----+----+----+----+----+
| T1 | T2 | T3 | T4 | T5 |
+----+----+----+----+----+
| NA | NA | NA | NA | 1  |
| NA | NA | 1  | 1  | 1  |
| NA | NA | 1  | NA | 1  |
| 1  | 0  | 0  | 0  | 0  |
| NA | NA | 1  | 0  | 0  |
| NA | NA | NA | NA | NA |
| NA | NA | NA | 1  | 0  |
| NA | NA | 1  | 0  | 1  |
| NA | NA | 1  | 1  | 0  |
+----+----+----+----+----+

向量1应该返回c(6,6,6,2,4,1,5,6,5),而向量2应该返回c(6,6,6,2,4,1,5,4,5)

我的第一次尝试是在下面,但这只会返回在每一列中找到1的最终位置

pattern <- matrix(data = NA, nrow = nrow(df), ncol = 1)
for (k in 1:ncol(df)) {
  df[, k][df[, k] > 0] <- k
}
pattern[, 1] <- apply(df, 1, function(x) max(x, na.rm = TRUE)+1)

我的第二次尝试看起来像这样

extInd <- function(x) {
  v1 <- max(which(x > 0)) + 1
  v2 <- min(which(x > 0)) + 1
  return(c(v1, v2))
}

apply(df, 1, extInd)

最大的问题是,我不确定如何检查出现的1是否仅由NA或0分隔,然后根据将它们分开的值来更改返回结果。

1 个答案:

答案 0 :(得分:0)

我想与同事交谈后我可能已经解决了这个问题。我们可以在出现1的情况下返回最大列号+1,在最小列号0时返回。如果没有1,则返回1。如果没有零,则返回1的值。

structure(list(T1 = c(NA, NA, NA, 1L, NA, NA, NA, NA, NA), T2 = c(NA, 
NA, NA, 0L, NA, NA, NA, NA, NA), T3 = c(NA, 3L, 3L, 0L, 3L, NA, 
NA, 3L, 3L), T4 = c(NA, 4L, NA, 0L, 0L, NA, 4L, 0L, 4L), T5 = c(5L, 
5L, 5L, 0L, 0L, NA, 0L, 5L, 0L)), row.names = c(NA, -9L), class = "data.frame")

extInd <- function(x) {
  ## check where 1 occurs and return max(x)+1
  pos_1 <- max(which(x == 1), na.rm = TRUE) + 1
  ## if never, return 1
  if (is.infinite(pos_1)) {
    pos_1 <- 1
  }
  ## check where 0 occurs and return first instance
  pos_0 <- min(which(x == 0), na.rm = TRUE)
  ## if never 0, return pos_1
  if (is.infinite(pos_0)) {
    pos_0 <- pos_1
  }
  return(c(pos_1, pos_0))
}

suppressWarnings(t(apply(df, 1, extInd)))