我们可以将 data.frame 拆分成一个 data.frames 列表并在base R中进行替换
df1 <- do.call(cbind, lapply(split.default(df,
sub("\\..*", "", names(df))), function(x) {
x[,1][x[2] == 0] <- NA
x}))
或者另一个选项是Map
acols <- endsWith(names(df), "a")
bcols <- endsWith(names(df), "b")
df[acols] <- Map(function(x, y) replace(x, y == 0, NA), df[acols], df[bcols])
或者如果列与'a'、'b'列交替,使用逻辑索引进行回收,用'b'列创建逻辑矩阵并将'a'列中的对应值赋给NA
df[c(TRUE, FALSE)][df[c(FALSE, TRUE)] == 0] <- NA
或tidyverse 的选项,通过重塑为“长”格式(pivot_longer),如果“a”中有相应的 0,则将“a”列更改为 NA,然后重新整形为“宽” ' 格式为pivot_wider
library(dplyr)
library(tidyr)
df %>%
mutate(rn = row_number()) %>%
pivot_longer(cols = -rn, names_sep="\\.",
names_to = c('group', '.value')) %>%
mutate(a = na_if(b, a == 0)) %>%
pivot_wider(names_from = group, values_from = c(a, b)) %>%
select(-rn)
# A tibble: 5 x 6
# a_sample1 a_sample2 a_sample3 b_sample1 b_sample2 b_sample3
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 2 1 2 2 1 2
#2 2 3 2 2 3 2
#3 2 3 2 2 3 2
#4 2 3 2 2 3 2
#5 2 3 2 2 3 2