循环多列以应用条件转换

问题描述 投票:0回答:1

我正在尝试创建以下循环:

循环columns_to_check(10列),如果没有值(即NA)则NA。结束循环。 如果不适用,请检查以下条件:

  • 如果值为2或4,则对应的新列值应为0。
  • 如果是该行中第一次出现 1,3 或 5,则相应的新值应为 1。
  • 如果不是该行中第一次出现 1,3 或 5,则相应的新值应为 0。
  • 否则999。

使用循环结果创建 10 个新列,并将它们标记为 stp_result_(值 1 到 10。

这是我的数据框:

df <- structure (list(
  subject_id = c("5467", "6784", "3457", "0987", "1245", "1945","3468", "0012","0823","0812"), 
  stp_t_1 = c(1,3,5,1,2,5,4,3,3,1),
  stp_t1_cor = c(0,0,0,0,0,0,0,0,0,0), 
  stp_t1_cor_num = c(NA,NA,NA,NA,NA,NA,NA,NA,NA,NA),
  stp_t_2 = c(2,5,1,3,5,1,3,2,2,3), 
  stp_t2_cor = c(1,0,0,0,0,0,0,0,0,0), 
  stp_t2_cor_num = c(1,NA,NA,NA,NA,NA,NA,NA,NA,NA), 
  stp_t_3 = c(3,2,5,4,3,3,3,3,1,5),
  stp_t3_cor = c(0,1,0,0,0,0,0,0,0,0),
  stp_t3_cor_num = c(NA,4,NA,NA,NA,NA,NA,NA,NA),
  stp_t_4 = c(4,1,4,3,NA,NA,1,2,5,NA),
  stp_t4_cor = c(1,0,0,0,NA,NA,0,0,0,0),
  stp_t4_cor_num = c(1,NA,NA,NA,NA,NA,NA,NA,NA),
  stp_t_5 = c(5,NA,3,1,NA,NA,1,3,NA,NA),
  stp_t5_cor = c(0,NA,0,0,NA,NA,0,0,NA,NA),
  stp_t5_cor_num = c(NA,NA,NA,NA,NA,NA,NA,NA,NA,NA),
  stp_t_6 = c(NA,NA,NA,NA,NA,NA,4,4,NA,NA),
  stp_t6_cor = c(NA,NA,NA,NA,NA,NA,0,0,NA,NA), 
  stp_t6_cor_num = c(NA,NA,NA,NA,NA,NA,NA,NA,NA,NA),
  stp_t_7 = c(NA,NA,NA,NA,NA,NA,5,5,NA,NA), 
  stp_t7_cor = c(NA,NA,NA,NA,NA,NA,0,0,NA,NA), 
  stp_t7_cor_num = c(NA,NA,NA,NA,NA,NA,NA,NA,NA,NA), 
  stp_t_8 = c(NA,NA,NA,NA,NA,NA,2,1,NA,NA),
  stp_t8_cor = c(NA,NA,NA,NA,NA,NA,0,0,NA,NA),
  stp_t8_cor_num = c(NA,NA,NA,NA,NA,NA,NA,NA,NA,NA),
  stp_t_9 = c(NA,NA,NA,NA,NA,NA,1,3,NA,NA),
  stp_t9_cor = c(NA,NA,NA,NA,NA,NA,0,0,NA,NA),
  stp_t9_cor_num = c(NA,NA,NA,NA,NA,NA,NA,NA,NA,NA),
  stp_t_10 = c(NA,NA,NA,NA,NA,NA,1,2,NA,NA),
  stp_t10_cor = c(NA,NA,NA,NA,NA,NA,0,0,NA,NA),
  stp_t10_cor_num = c(NA,NA,NA,NA,NA,NA,NA,NA,NA,NA)), 
  class = "data.frame", row.names = c(NA, -10L))

这是我尝试过的:

columns_to_check <- grep("stp_t_", names(df), value = TRUE)

for (i in 1:length(columns_to_check)) {
  col_name <- columns_to_check[i]
  new_col_name <- paste0("stp_result_", i)
  
  result <- rep(NA, nrow(df))
  
  for (j in 1:nrow(df)) {
    value <- df[[col_name]][j]
    
    if (is.na(value)) {
      result[j] <- NA 
    } else if (value %in% c(2, 4)) {
      result[j] <- 0   
    } else if (value %in% c(1, 3, 5)) {
      if (value %in% c(1, 3, 5) && !any(!is.na(result[1:j - 1]) & result[1:j - 1] == 1)) {
        result[j] <- 1   
      } else {
        result[j] <- 0   
      }
    } else {
      result[j] <- 999 
    }
  }
  df[[new_col_name]] <- result
}

我认为整个循环不起作用。它会产生很多 0,并将其他错误地表述为 1。不知道我哪里出错了。

期望的结果将是带有新列的原始 df:

subject_id  stp_result_1  stp_result_2  stp_result_3  stp_result_4  stp_result_5  stp_result_6  stp_result_7  stp_result_8  stp_result_9  stp_result_10
5467        1             0             1             0             1             NA            NA            NA            NA            NA
6784        1             1             0             1             NA            NA            NA            NA            NA            NA
3457        1             1             0             0             1             NA            NA            NA            NA            NA
0987        1             1             0             0             0             NA            NA            NA            NA            NA
1245        1             1             1             NA            NA            NA            NA            NA            NA            NA
1945        1             1             1             NA            NA            NA            NA            NA            NA            NA
3468        0             1             0             1             0             0             1             0             0             0
0012        1             0             0             0             0             0             1             1             0             0
0823        1             0             1             1             NA            NA            NA            NA            NA            NA
0812        1             1             1             NA            NA            NA            NA            NA            NA            NA
r dplyr
1个回答
1
投票

这是一个检查并应用条件的函数,无需循环,

for
或其他。代码
sapply
是对每一列进行检查的函数,并返回一个可以与原始 data.frame 进行
cbind
的矩阵。

fun <- function(x) {
  # default value
  y <- rep(999, length(x))
  # assign NA to y if x is NA
  is.na(y) <- is.na(x)
  # assign 0 to all y where x is 2 or 4
  y[x %in% c(2, 4)] <- 0
  # now check values 1, 3, 5
  for(i in c(1, 3, 5)) {
    if(any(x == i, na.rm = TRUE)) {
      w <- which(x == i)
      # y gets a 1 for the first such values 
      y[ w[1L] ] <- 1
      # and a 0 if more exist
      if(length(w) > 1L) y[ w[-1L] ] <- 0
    }
  }
  y
}

columns_to_check <- grep("stp_t_", names(df), value = TRUE)

res <- apply(df[columns_to_check], 1, fun) |> t()
colnames(res) <- paste0("stp_result_", seq_along(columns_to_check))
res

cbind(df, res)

创建于 2024-05-03,使用 reprex v2.1.0


编辑

看看这是否有效:

apply(df[columns_to_check], 1, fun) |> t()
© www.soinside.com 2019 - 2024. All rights reserved.