【问题标题】:Loop over columns of a data.frame to apply a condition循环 data.frame 的列以应用条件
【发布时间】:2019-04-11 14:15:42
【问题描述】:

我有一个这样的data.frame:

        name       value1      value2     value3   
          a          0.10         0.9       0.10
          b          0.00         0.3       0.67
          c          0.01         0.1       0.10
          d          0.12         0.10      0.2
          e          0.10         0.001     0.1       

对于每一列“value*”我想,名字对应的值是0.10。换句话说,输出将是一个包含“名称”元素的三列数据框。我开始的想法是将“名称”与每个“值*”列绑定到子集,但没有成功:

 for(i in 1:length(mydf)){    
      my_subset[[i]] = cbind(rownames(mydf), mydf[[i]])    
 }

“名称”列是 mydf 的行名。此外,我总共有 10.000 行和 45 列。

期望的输出:

        name       value1      value2     value3   
          a          a           NA        a
          b          NA          NA        NA
          c          NA          NA        c
          d          NA          d         NA
          e          e           NA        NA       

谁能帮帮我?我知道有一些“应用”函数可能可以完成这项工作,但我不得不学习如何使用 for 循环。

提前谢谢你

【问题讨论】:

  • 你能发布你想要的输出吗?
  • 我强调前面的评论,您可以像这样将行名添加为新列:mydf$name_col <- rownames(mydf)
  • 0.1 等于 0.10 吗?!

标签: r for-loop


【解决方案1】:

这是你想要的吗?

a = structure(list(value1 = c("0.10", "0.00", "0.01", "0.12", "0.10"
), value2 = c("0.9", "0.3", "0.1", "0.10", "0.001"), value3 = c("0.10", 
"0.67", "0.10", "0.2", "0.1")), row.names = c("a", "b", "c", 
"d", "e"), class = "data.frame")

val = "0.10"
apply(a,2,function(x) rownames(a)[which(x==val)])

$`value1`
[1] "a" "e"

$value2
[1] "d"

$value3
[1] "a" "c"

【讨论】:

  • 为什么不用 c 和 d?
  • 是的! Nelson 不是 c/d,因为要求不是 >0.10 而是相等
  • 这意味着 0.1!=0.10 那么!
  • @NelsonGon 这就是我的想法,这就是为什么我将值视为character
【解决方案2】:

这是使用 for 循环的替代方法

X <- data.frame(
    name = letters[1:5],
    value1 = c(0.10, 0.00, 0.01, 0.12, 0.10),
    value2 = c(0.90, 0.30, 0.10, 0.10, 0.001),
    value3 = c(0.10, 0.67, 0.10, 0.20, 0.10),
    stringsAsFactors = FALSE
)

示例数据:

X
  name value1 value2 value3
1    a   0.10  0.900   0.10
2    b   0.00  0.300   0.67
3    c   0.01  0.100   0.10
4    d   0.12  0.100   0.20
5    e   0.10  0.001   0.10
for (j in grep("value", names(X))) {
    X[, j] <- ifelse(X[, j] == 0.10, X[, "name"], NA)
}

结果:

X
  name value1 value2 value3
1    a      a   <NA>      a
2    b   <NA>   <NA>   <NA>
3    c   <NA>      c      c
4    d   <NA>      d   <NA>
5    e      e   <NA>      e

【讨论】:

    【解决方案3】:

    带基 R lapply

    cols <- grep("^value", names(df))
    df[cols] <- lapply(df[cols], function(x) ifelse(x == 0.1, df$name, NA))
    
    
    df
    #  name value1 value2 value3
    #1    a      a   <NA>      a
    #2    b   <NA>   <NA>   <NA>
    #3    c   <NA>      c      c
    #4    d   <NA>      d   <NA>
    #5    e      e   <NA>      e
    

    【讨论】:

      【解决方案4】:

      这是base R的矢量化方法

      df[-1] <- df$name[NA^(df[-1] != 0.1) * seq_len(nrow(df))]
      df
      #    name value1 value2 value3
      #1    a      a   <NA>      a
      #2    b   <NA>   <NA>   <NA>
      #3    c   <NA>      c      c
      #4    d   <NA>      d   <NA>
      #5    e      e   <NA>      e
      

      基准测试

      df1 <- df[rep(seq_len(nrow(df)), 1e7), ]
      
      df2 <- copy(df1)
      
      system.time({
      cols <- grep("^value", names(df1))
      df1[cols] <- lapply(df1[cols], function(x) ifelse(x == 0.1, df1$name, NA))
      })
      #    user  system elapsed 
      #  35.700   4.587  40.615 
      system.time({
       df2[-1] <- df2$name[NA^(df2[-1] != 0.1) * seq_len(nrow(df2))]
      
      })
      #   user  system elapsed 
      # 21.709   3.886  26.026 
      

      数据

      df <- structure(list(name = c("a", "b", "c", "d", "e"), value1 = c(0.1, 
       0, 0.01, 0.12, 0.1), value2 = c(0.9, 0.3, 0.1, 0.1, 0.001), value3 = c(0.1, 
        0.67, 0.1, 0.2, 0.1)), class = "data.frame", row.names = c(NA, 
       -5L))
      

      【讨论】:

        【解决方案5】:

        你可以简单地使用data.table package-

        > setDT(dt)[,(setdiff(colnames(dt),"name")):=lapply(.SD,function(x) ifelse(x==.10,as.character(name),NA)),.SDcols=setdiff(colnames(dt),"name")]
        
        > dt
           name value1 value2 value3
        1:    a      a   <NA>      a
        2:    b   <NA>   <NA>   <NA>
        3:    c   <NA>      c      c
        4:    d   <NA>      d   <NA>
        5:    e      e   <NA>      e
        

        【讨论】:

          猜你喜欢
          • 2012-07-11
          • 1970-01-01
          • 2020-05-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-04-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多