【问题标题】:Use lapply to change all elements of a certain value to another value, on a colum by column basis in R使用 lapply 在 R 中逐列将某个值的所有元素更改为另一个值
【发布时间】:2021-06-09 19:23:09
【问题描述】:

对于数据框中的每一列,我想用列号替换所有非零值。 即,如果我有一个像这样的数据框:

> df1 <- as.data.frame(matrix(c(0,0.1,0,0.1,0,0.1,0,0.1,0,0.1,0,0.1), nrow = 4, ncol = 3))
> df1
   V1  V2  V3
1 0.0 0.0 0.0
2 0.1 0.1 0.1
3 0.0 0.0 0.0
4 0.1 0.1 0.1

我想改成:

>df2
  V1 V2 V3
1  0  0  0  
2  1  2  3
3  0  0  0
4  1  2  3

我在以下方面尝试了多种变体但没有成功 - 我无法理解 lapply 调用中的函数所指的内容。

  counter <- 0
  lapply(df1, function(x){
    df1[,x][df1[,x]>0] <- counter
    counter <<- counter+1
  })

  counter <- 0
  lapply(df1, function(x){
    x[][x[]>0] <- counter
    counter <<- counter+1
  })

【问题讨论】:

    标签: r dataframe indexing lapply


    【解决方案1】:

    可以用更紧凑的方式完成

    df1[] <-  col(df1) * !!df1
    

    -输出

    df1
    #  V1 V2 V3
    #1  0  0  0
    #2  1  2  3
    #3  0  0  0
    #4  1  2  3
    

    将“df1”转换为逻辑矩阵,即 TRUE 表示非零值,FALSE 表示零 (!!df1) 并与列索引 (col(df1)) 相乘,以便任何值为 FALSE -> 0 的值,以及那些为 TRUE -> 1 的,返回列索引


    或者dplyr中的另一个选项

    library(dplyr)
    df1 %>% 
       mutate(across(everything(), ~  match(cur_column(), names(df1)) * (. != 0)))
    

    【讨论】:

    • 非常感谢 - 绝对优雅,将使用它并将我从 @gregorthomas 获得的新知识放在我的后兜里。
    【解决方案2】:

    如果您想使用 lapply 并访问列号,请遍历列号:

    df1[] = lapply(seq_along(df1), function(i) {
      replace(df1[[i]], df1[[i]] != 0, i)
    })
    
    df1
    #   V1 V2 V3
    # 1  0  0  0
    # 2  1  2  3
    # 3  0  0  0
    # 4  1  2  3
    

    当使用lapply 就地修改列时,请记住分配必须在lapply 调用之外进行。使用像data[] = lapply(...) 这样的括号是一个有用的技巧,这样lapply 返回的list 会被解释为数据框的列。

    【讨论】:

    • 谢谢!我也尝试过迭代列号但无济于事 - 但我现在看到我的主要问题是我在函数中引用列索引,就好像它们在 df 中而不是在列表中一样。
    • 您可以将我的df1[[i]] 替换为df1[, i] 并获得相同的结果。当我知道我想要一个单列时,我更喜欢使用[[。我认为你更大的问题是试图在lapply 中分配给df1,而主要分配需要是lapply 结果。
    猜你喜欢
    • 2017-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-13
    • 1970-01-01
    相关资源
    最近更新 更多