我有一个这样的数据集:
dat1 <- read.table(text = "
nodepair 3 4 5
1 A6_A1 2 5 1
2 A6_A2 2 5 1
3 A6_A3 2 5 1
4 AL_A1 1 0 0
5 D_A6 0 3 0
6 F_A1 1 0 1
7 H_D 0 0 2
8 H_H 0 0 2
", header = TRUE, check.names = FALSE)
我需要编写一个程序来有效地创建新列,当对之间出现零时,该新列对每个成对比较进行求和——具体来说,创建“b”条件是当节点对对第一个变量唯一但不是第二个变量时,并且“c”条件是当节点对对于第二个而不是第一个节点是唯一的时。这是所需的输出:
dat2 <- read.table(text = "
nodepair 3 4 5 3-4b 3-4c 3-5b 3-5c 4-5b 4-5c
1 A6_A1 2 5 1 NA NA NA NA NA NA
2 A6_A2 2 5 1 NA NA NA NA NA NA
3 A6_A3 2 5 1 NA NA NA NA NA NA
4 AL_A1 1 0 0 1 NA 1 NA 0 0
5 D_A6 0 3 0 NA 3 0 0 3 NA
6 F_A1 1 0 1 1 NA NA NA NA 1
7 H_D 0 0 2 0 0 NA 2 NA 2
8 H_H 0 0 2 0 0 NA 2 NA 2
", header = TRUE, check.names = FALSE)
这段代码可以工作,但对于我更大的数据集来说肯定不太理想:
dat1 <- dat1 %>%
mutate('3-4b' = case_when(`4` == 0 ~ as.integer(rowSums(across(c(`3`,`4`)))))) %>%
mutate('3-4c' = case_when(`3` == 0 ~ as.integer(rowSums(across(c(`3`,`4`)))))) %>%
mutate('3-5b' = case_when(`5` == 0 ~ as.integer(rowSums(across(c(`3`,`5`)))))) %>%
mutate('3-5c' = case_when(`3` == 0 ~ as.integer(rowSums(across(c(`3`,`5`)))))) %>%
mutate('4-5b' = case_when(`5` == 0 ~ as.integer(rowSums(across(c(`4`,`5`)))))) %>%
mutate('4-5c' = case_when(`4` == 0 ~ as.integer(rowSums(across(c(`4`,`5`))))))
在 R 基础中,您可以编写一个小函数来完成任务,并使用
combn
迭代 2 个组合:
fn <- function(x){
i1 <- x[, 1] == 0
i2 <- x[, 2] == 0
x[] <- ifelse(i1 | i2, rowSums(x), NA)
x[i1, 1] <- NA
x[i2, 2] <- NA
x[i1&i2,] <- 0
names(x) <- paste0(paste(names(x), collapse = "-"), c('b','c'))
x
}
cbind(dat1,do.call(cbind, combn(dat1[-1], 2, fn, simplify = FALSE)))
nodepair 3 4 5 3-4b 3-4c 3-5b 3-5c 4-5b 4-5c
1 A6_A1 2 5 1 NA NA NA NA NA NA
2 A6_A2 2 5 1 NA NA NA NA NA NA
3 A6_A3 2 5 1 NA NA NA NA NA NA
4 AL_A1 1 0 0 1 NA 1 NA 0 0
5 D_A6 0 3 0 NA 3 0 0 3 NA
6 F_A1 1 0 1 1 NA NA NA NA 1
7 H_D 0 0 2 0 0 NA 2 NA 2
8 H_H 0 0 2 0 0 NA 2 NA 2