根据配对列替换值
Replacing value depending on paired column
我有一个数据框,每个样本有两列(n > 1000 个样本):
df <- data.frame(
"sample1.a" = 1:5, "sample1.b" = 2,
"sample2.a" = 2:6, "sample2.b" = c(1, 3, 3, 3, 3),
"sample3.a" = 3:7, "sample3.b" = 2)
如果.b列中有零,则.a列中的相应值应设置为NA。
我想在 colnames(没有后缀)上写一个函数来过滤每对列和条件交换值。有没有更简单的基于tidyverse的方法?
我们可以将 data.frame 拆分为 data.frame 的列表,然后在 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
的选项,方法是重塑为 'long' 格式 (pivot_longer
),如果有相应的格式,则将 'a' 列更改为 NA
'a' 中的 0,并使用 pivot_wider
重塑回 'wide' 格式
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
我有一个数据框,每个样本有两列(n > 1000 个样本):
df <- data.frame(
"sample1.a" = 1:5, "sample1.b" = 2,
"sample2.a" = 2:6, "sample2.b" = c(1, 3, 3, 3, 3),
"sample3.a" = 3:7, "sample3.b" = 2)
如果.b列中有零,则.a列中的相应值应设置为NA。
我想在 colnames(没有后缀)上写一个函数来过滤每对列和条件交换值。有没有更简单的基于tidyverse的方法?
我们可以将 data.frame 拆分为 data.frame 的列表,然后在 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
的选项,方法是重塑为 'long' 格式 (pivot_longer
),如果有相应的格式,则将 'a' 列更改为 NA
'a' 中的 0,并使用 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