使用 lapply 将某个值的所有元素更改为另一个值,在 R 中的逐列基础上

Use lapply to change all elements of a certain value to another value, on a colum by column basis in R

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

> 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
  })

可以用更紧凑的方式来完成

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,returns 列索引


dplyr

中的另一个选项
library(dplyr)
df1 %>% 
   mutate(across(everything(), ~  match(cur_column(), names(df1)) * (. != 0)))

如果您想使用 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 被解释为数据框的列。