代码之家  ›  专栏  ›  技术社区  ›  Ilya Rusin

对于每一行,返回非NA值的列索引和名称

na r
  •  2
  • Ilya Rusin  · 技术社区  · 10 年前

    我有一个数据帧,其中每行包含一个非- NA 价值

    ED1 ED2 ED3 ED4 ED5 
    1   NA  NA  NA  NA 
    NA  NA  1   NA  NA 
    NA  1   NA  NA  NA 
    NA  NA  NA  NA  1 
    

    对于每一行,我想获取包含非- 值,即:

    指数: c(1, 3, 2, 5) ,及其相应的列名: c("ED1" "ED3" "ED2" "ED5")

    3 回复  |  直到 5 年前
        1
  •  7
  •   Rich Scriven    10 年前

    无需使用 apply() 在这里循环。你可以使用 max.col() 与对 is.na() .

    max.col(!is.na(df))
    # [1] 1 3 2 5
    

    这就给出了1所在的列号。要获得列名,我们可以在 names() 数据帧的。

    names(df)[max.col(!is.na(df))]
    # [1] "ED1" "ED3" "ED2" "ED5"
    

    因此,我们可以通过以下操作获得所需的数据帧,包括因子列

    data.frame(EDU = names(df)[max.col(!is.na(df))])
    #   EDU
    # 1 ED1
    # 2 ED3
    # 3 ED2
    # 4 ED5
    

    数据:

    df <- structure(list(ED1 = c(1, NA, NA, NA), ED2 = c(NA, NA, 1, NA), 
        ED3 = c(NA, 1, NA, NA), ED4 = c(NA, NA, NA, NA), ED5 = c(NA, 
        NA, NA, 1)), .Names = c("ED1", "ED2", "ED3", "ED4", "ED5"
    ), row.names = c(NA, -4L), class = "data.frame")
    
        2
  •  1
  •   mra68    10 年前
    df <- data.frame( ED1 = c(  1, NA, NA, NA),
                      ED2 = c( NA, NA, 1 , NA),
                      ED3 = c( NA,  1, NA, NA),
                      ED4 = c( NA, NA, NA, NA),
                      ED5 = c( NA, NA, NA,  1)  )
    
    df_new <- data.frame( EDU = as.factor(apply(df,1,which.min)) )
    levels(df_new$EDU) <- paste0("ED",levels(df_new$EDU))
    

    .

    > df
      ED1 ED2 ED3 ED4 ED5
    1   1  NA  NA  NA  NA
    2  NA  NA   1  NA  NA
    3  NA   1  NA  NA  NA
    4  NA  NA  NA  NA   1
    > df_new
      EDU
    1 ED1
    2 ED3
    3 ED2
    4 ED5
    
        3
  •  1
  •   akrun    10 年前

    另一种选择是

     v1 <- names(df)[+(!is.na(df)) %*% seq_along(df)]
     v1
     #[1] "ED1" "ED3" "ED2" "ED5"
    
     data.frame(EDU=v1)
    

    或使用 pmax

    names(df)[do.call(pmax, c(df *col(df), list(na.rm=TRUE)))]
    #[1] "ED1" "ED3" "ED2" "ED5"