R 嵌套if-else语句

R 嵌套if-else语句,r,if-statement,R,If Statement,我有一个大数据集需要重新编码。数据集的每一行都是按时间顺序(时间)从单独的实验(id)中可能检测到的。然后手动验证每个可能的检测。当进行第一次真实检测时,标记为(注释)“第一次”。当进行最后一次真实检测时,标记为“最后一次”。如果没有检测,则输入“无” 我正准备用if语句重新编码。1) 首先,我想选择变量id的所有情况,其中First和last都存在,然后它需要用“no_comment”填充First和last之间的所有内容,然后它需要用“MVND”填充First和last之前或之后的所有内容。

我有一个大数据集需要重新编码。数据集的每一行都是按时间顺序(时间)从单独的实验(id)中可能检测到的。然后手动验证每个可能的检测。当进行第一次真实检测时,标记为(注释)“第一次”。当进行最后一次真实检测时,标记为“最后一次”。如果没有检测,则输入“无”

我正准备用if语句重新编码。1) 首先,我想选择变量id的所有情况,其中First和last都存在,然后它需要用“no_comment”填充First和last之间的所有内容,然后它需要用“MVND”填充First和last之前或之后的所有内容。2) 选择仅显示“无”的id案例,并在该id案例的所有行中填充“无”。单独的代码行可以工作,但由于某种原因,当我在ddply中的if语句中组合它们时,它们不能一起工作-它们只返回原始的data.frame。我想我想做的事情的if-else结构是错误的

#approximate data structure for this case:
y <-data.frame(id=c(rep("a",10),rep("b",10),rep("c",10)),time=rep(1:10, 3), Comments=rep(NA,30))
 y$Comments[c(2,11,23)]<-"first"
 y$Comments[c(9,19,30)]<-"last"
 #x=y[y$id=="a",] #testing specific lines
 
#recursive process to step through the data
 ddply(y,.(id), .fUN=function(x){
 if(all(unique(na.omit(x$Comments))%in%c("first","last"))){
  f<-which(x$Comments == "first")
  l<-which(x$Comments == "last")  
  #Add no comment to all records between first and last
   x$Comments[(f+1):(l - 1)]<- "no_comment"
      #if 'first' isn't the first record add MVND to all things before 'first'    
       if(f>1){x$Comments[1:(f-1)]<-"MVND"} 
      #if 'last' isn't the last record add MVND to all records after 'last'.
       if(l<nrow[x]){x$Comments[(l+1):nrow(x)]<-"MVND"} 
 }else if(unique(na.omit(x$Comments))=="none"){
    x$Comments<-"none" #if the only unique comment is "none" set all comments to none
}
 }
 )
#这种情况下的近似数据结构:

y不确定是否对您有用,但以下是我在
dplyr
中的方法。由于这是矢量化的,我希望它比基于循环的方法运行得更快

library(dplyr)
y %>%
  group_by(id) %>%
  dplyr::mutate(Comments2 = case_when(     # in case `plyr` is loaded
    cumsum(coalesce(lag(Comments == "last"), FALSE)) >= 1 ~ "MVND",
    cumsum(coalesce(Comments == "first", FALSE)) < 1 ~ "MVND",
    is.na(Comments) ~ "no_comment",
    TRUE ~ Comments)) %>%
  ungroup()

不确定是否对您有用,但以下是我在
dplyr
中的方法。由于这是矢量化的,我希望它比基于循环的方法运行得更快

library(dplyr)
y %>%
  group_by(id) %>%
  dplyr::mutate(Comments2 = case_when(     # in case `plyr` is loaded
    cumsum(coalesce(lag(Comments == "last"), FALSE)) >= 1 ~ "MVND",
    cumsum(coalesce(Comments == "first", FALSE)) < 1 ~ "MVND",
    is.na(Comments) ~ "no_comment",
    TRUE ~ Comments)) %>%
  ungroup()

对于此任务,我首选的方法是
data.table
,原因有二:

  • 可以就地更新列的某些部分,即无需复制
  • 我们可以使用查找表在非等联接中进行更新
  • 为了涵盖OP提到的所有用例,我们需要创建一个增强的示例数据集

    y <- data.frame(
      id = rep(letters[1:5], each = 5L),
      time = rep(1:5, 5L),
      Comments = rep(NA_character_, 25L))
    y$Comments[c(2, 6, 13, 22)] <- "first"
    y$Comments[c(4, 9, 15, 23)] <- "last"
    y$Comments[c(18)] <- "none"
    
    y
    
    查找表
    lut
    包含
    first
    last
    分别出现的时间:

    注意,我们假设生产数据集“表现良好”,即

    • 任何
      id
      组都包含
      “无”
    • 或者在
      注释
      列中正好有一对
      “first”
      “last”
    • “第一个”
      总是出现在
      “最后一个”
      之前

    对于此任务,我首选的方法是
    数据。表
    有两个原因:

  • 可以就地更新列的某些部分,即无需复制
  • 我们可以使用查找表在非等联接中进行更新
  • 为了涵盖OP提到的所有用例,我们需要创建一个增强的示例数据集

    y <- data.frame(
      id = rep(letters[1:5], each = 5L),
      time = rep(1:5, 5L),
      Comments = rep(NA_character_, 25L))
    y$Comments[c(2, 6, 13, 22)] <- "first"
    y$Comments[c(4, 9, 15, 23)] <- "last"
    y$Comments[c(18)] <- "none"
    
    y
    
    查找表
    lut
    包含
    first
    last
    分别出现的时间:

    注意,我们假设生产数据集“表现良好”,即

    • 任何
      id
      组都包含
      “无”
    • 或者在
      注释
      列中正好有一对
      “first”
      “last”
    • “第一个”
      总是出现在
      “最后一个”
      之前

    感谢您尝试一下。这个答案看起来应该有用,但当我在我的电脑上运行它时,它只在第一个案例中运行,而不是在随后的两个案例中运行。y2$2。。。不知何故,group_by(id)没有做它应该做的事情。您对示例数据的回答是否与我的不同,或者您是说在单独的数据上运行时得到了意外的结果?这可能是一个
    plyr
    /
    dplyr
    名称冲突的问题,因为它们不幸共享了一些函数名称。我将进行编辑,使代码中的冲突更加明确。好吧,这一定是我听说过但还没有遇到的奇怪冲突之一。这能帮你解决问题吗?谢谢你尝试一下。这个答案看起来应该有用,但当我在我的电脑上运行它时,它只在第一个案例中运行,而不是在随后的两个案例中运行。y2$2。。。不知何故,group_by(id)没有做它应该做的事情。您对示例数据的回答是否与我的不同,或者您是说在单独的数据上运行时得到了意外的结果?这可能是一个
    plyr
    /
    dplyr
    名称冲突的问题,因为它们不幸共享了一些函数名称。我将对其进行编辑,使其在代码中显式显示。好吧,这一定是我听说过但尚未遇到的奇怪冲突之一。这能为您解决问题吗?这很好地扩展到了生产数据集-data.table,这让我感到惊讶。我还没有遇到“on”,你能给我指一下关于这个的文档吗?我不太明白为什么
    y[lut,on=(id,time>first,time
    有效,但是
    y[lut,on=(id,timelast)
    无效。这很好地扩展到了生产数据集-data.table。我从未遇到过“on”你能给我指一下这方面的文档吗?我不太明白为什么
    y[lut,on=(id,time>first,time
    有效,但
    y[lut,on=(id,timelast)
    无效。
    library(data.table)
    y <- setDT(copy(y))
    # copy "none" to all rows of the id group in case one Comment is "none" 
    y[, Comments := if (isTRUE(any(Comments == "none"))) "none" , by = id][]
    # create look-up table
    lut <- dcast(y[which(Comments %in% c("first", "last"))], id ~ Comments, value.var = "time")
    # update in non-equi joins
    y[lut, on = .(id, time < first), Comments := "MVND"][]
    y[lut, on = .(id, time > last), Comments := "MVND"][]
    y[lut, on = .(id, time > first, time < last), Comments := "no commments"][]
    
        id time     Comments
     1:  a    1         MVND
     2:  a    2        first
     3:  a    3 no commments
     4:  a    4         last
     5:  a    5         MVND
     6:  b    1        first
     7:  b    2 no commments
     8:  b    3 no commments
     9:  b    4         last
    10:  b    5         MVND
    11:  c    1         MVND
    12:  c    2         MVND
    13:  c    3        first
    14:  c    4 no commments
    15:  c    5         last
    16:  d    1         none
    17:  d    2         none
    18:  d    3         none
    19:  d    4         none
    20:  d    5         none
    21:  e    1         MVND
    22:  e    2        first
    23:  e    3         last
    24:  e    4         MVND
    25:  e    5         MVND
        id time     Comments
    
       id first last
    1:  a     2    4
    2:  b     1    4
    3:  c     3    5
    4:  e     2    3