R. 如果两列匹配,则有条件地替换数据框中的字符

R. Conditional replace of characters in data frame if two columns match

我有一个包含列 c1 到 c11 的数据框,如下所示:

c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11  
G A G 1 1 0 1 1 0 0 1
T C T 0 0 1 1 0 1 0 1
C C T 0 1 1 1 1 1 1 0

我想这样做:如果c1中的字符与c3中的字符相同,则将c4替换为c11,1s替换为2s,0s替换为3s。否则,将 1s 替换为 3s,将 0s 替换为 2s

最后我会得到这个数据框:

c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11  
G A G 2 2 3 2 2 3 3 2
T C T 3 3 2 2 3 2 3 2
C C T 2 3 3 3 3 3 3 2

1) 将 x = 0, 1 转换为 y = 3, 2 与从 3 减去 x 相同。同样将 x = 0, 1 转换为 y = 2, 3 等于 x 加 2。因此:

DF[4:11] <- with(DF, (c1 == c3) * (3 - DF[4:11]) + (c1 != c3) * (DF[4:11] + 2))

给予:

> DF
  c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11
1  G  A  G  2  2  3  2  2  3   3   2
2  T  C  T  3  3  2  2  3  2   3   2
3  C  C  T  2  3  3  3  3  3   3   2

2) 也可以这样写,虽然更长,但从定义上更直接:

DF[4:11] <- with(DF, (c1 == c3) * (2 * (DF[4:11] == 1) + 3 * (DF[4:11] == 0)) +
                     (c1 != c3) * (3 * (DF[4:11] == 1) + 2 * (DF[4:11] == 0)))

备注

我们用这个作为输入。请注意,c1c2c3 被假定为字符,而不是因子,其余为数字。

Lines <- "
c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11  
G A G 1 1 0 1 1 0 0 1
T C T 0 0 1 1 0 1 0 1
C C T 0 1 1 1 1 1 1 0"
DF <- read.table(text = Lines, header = TRUE, as.is = TRUE)

尝试以下操作。它使用嵌套 ifelse 和索引向量。也许有更简单的方法,但这个只使用基础 R.

fun <- function(x){
    ifelse(inx,
        ifelse(x == 1, 2, 3),
        ifelse(x == 1, 3, 2)
    )
}

inx <- as.character(data$c1) == as.character(data$c3)
data[4:11]  <- lapply(data[4:11], fun)