【问题标题】:Store first non-missing value in a new column将第一个非缺失值存储在新列中
【发布时间】:2018-09-13 10:29:45
【问题描述】:

Ciao,我有几列代表分数。对于每个学生,我想获取第一个非 NA 分数并将其存储在一个名为 TEST 的新列中。

这是我的复制示例。这是我现在拥有的数据:

df <- data.frame(STUDENT=c(1,2,3,4,5), 
                 CLASS=c(90,91,92,93,95),
                 SCORE1=c(10,NA,NA,NA,NA), 
                 SCORE2=c(2,NA,8,NA,NA), 
                 SCORE3=c(9,6,6,NA,NA),
                 SCORE4=c(NA,7,5,1,9),
                 ROOM=c(01,02, 03, 04, 05))

这是我要添加的专栏:

df$FIRST <- c(10,6,8,1,9)

这是我的尝试:

df$FIRSTGUESS <- max.col(!is.na(df[3:6]), "first")

【问题讨论】:

    标签: r extract apply


    【解决方案1】:

    这正是dplyr 包中的dplyr 所做的。如其文档中所述:

    给定一组向量,coalesce() 找到第一个非缺失值 在每个位置。

    因此,你可以简化做:

    library(dplyr)
    df$FIRST <- do.call(coalesce, df[grepl('SCORE', names(df))])
    

    这是结果:

    > df
      STUDENT CLASS SCORE1 SCORE2 SCORE3 SCORE4 ROOM FIRST
    1       1    90     10      2      9     NA    1    10
    2       2    91     NA     NA      6      7    2     6
    3       3    92     NA      8      6      5    3     8
    4       4    93     NA     NA     NA      1    4     1
    5       5    95     NA     NA     NA      9    5     9
    

    【讨论】:

      【解决方案2】:

      您可以使用 applywhich.min(is.na(...)) 来做到这一点

      df$FIRSTGUESS <- apply(df[, grep("^SCORE", names(df))], 1, function(x) 
          x[which.min(is.na(x))])
      df
      #  STUDENT CLASS SCORE1 SCORE2 SCORE3 SCORE4 ROOM FIRSTGUESS
      #1       1    90     10      2      9     NA    1         10
      #2       2    91     NA     NA      6      7    2          6
      #3       3    92     NA      8      6      5    3          8
      #4       4    93     NA     NA     NA      1    4          1
      #5       5    95     NA     NA     NA      9    5          9
      

      请注意,我们需要is.na 而不是!is.na,因为FALSE 对应于0,我们希望返回第一个(which.min)FALSE 值。

      【讨论】:

        【解决方案3】:

        不幸的是,max.col 给出了最大值的索引,而不是值本身。但是,我们可以使用 mapply 调用将原始数据帧中的值作为子集。

        #Select only columns which has "SCORE" in it
        sub_df <- df[grepl("SCORE", names(df))]
        
        #Get the first non-NA value by row 
        inds <- max.col(!is.na(sub_df), ties.method = "first")
        
        #Get the inds value by row
        df$FIRSTGUESS <- mapply(function(x, y) sub_df[x,y], 1:nrow(sub_df), inds)
        
        df
        
        #  STUDENT CLASS SCORE1 SCORE2 SCORE3 SCORE4 ROOM FIRST FIRSTGUESS
        #1       1    90     10      2      9     NA    1    10         10
        #2       2    91     NA     NA      6      7    2     6          6
        #3       3    92     NA      8      6      5    3     8          8
        #4       4    93     NA     NA     NA      1    4     1          1
        #5       5    95     NA     NA     NA      9    5     9          9
        

        【讨论】:

        • 只是借用你的设置:-)
        【解决方案4】:

        使用zoo,na.locf,借用Ronaksub_df的设置

         df['New']=zoo::na.locf(t(sub_df),fromLast=T)[1,]
         df
          STUDENT CLASS SCORE1 SCORE2 SCORE3 SCORE4 ROOM New
        1       1    90     10      2      9     NA    1  10
        2       2    91     NA     NA      6      7    2   6
        3       3    92     NA      8      6      5    3   8
        4       4    93     NA     NA     NA      1    4   1
        5       5    95     NA     NA     NA      9    5   9
        

        【讨论】:

          猜你喜欢
          • 2021-09-03
          • 2014-06-12
          • 1970-01-01
          • 1970-01-01
          • 2019-07-18
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-10-21
          相关资源
          最近更新 更多