用 R 中的 apply 替换复杂的条件 for 循环

Replace a complex, conditional for loop with apply in R

我是 R 的新手,我希望用更多 eloquent 和更快的东西替换我凌乱的循环(申请?)。基本上,我想根据其他矩阵中相同位置的值是否相互匹配来填充一个新矩阵。让我举例说明:

>df1
  V1 V2 V3
1  A  G  A
2  T  T  T
3  C  A  A
4  G  C  G

 >df2
   V1
1  A
2  T
3  C
4  G

>df3
    V1   V2   V3
1  .25  .99  .41
2  .21  .25  .75
3  .35  .65  .55
4  .75  .21  .11

>newdf <- data.frame(matrix(ncol= ncol(df3), nrow = nrow(df3)))

请注意,df1 和 df3 将始终具有相同的维度,而 df2 将始终具有相同的 nrow。

If positions Match: If df1[i,j] == df2[i], then I want newdf[i,j] = df3[i,j]

如果位置不匹配:如果 df1[i,j] != df2[i],那么我想要 newdf[i,j] = 1-df3[i,j]

例如 df1[1,2] = 'G' 和 df2[1] = 'A', 所以我想要 newdf[1,2] = (1- df3[1,2] )

为了成功执行此操作,我写了一个非常粗糙的 for 循环:

df1<- as.matrix(df1)
df2<- as.matrix(df2)
df3<- as.matrix(df3)
newdf <- data.frame(matrix(ncol= ncol(df3), nrow = nrow(df3)))

for (i in (1:nrow(df1))){
  for (j in (1:ncol(df1))){
      if (df1[i,j] == df2[i]) {
        newdf[i,j] = df3[i,j] }
      else {
       newdf[i,j] = 1- df3[i,j] }
   }
 }

这给了我想要的结果:

>newdf
    X1   X2   X3
1 0.25 0.01 0.41
2 0.21 0.25 0.75
3 0.35 0.35 0.45
4 0.75 0.79 0.11

当我有大量数据时,这是一个非常缓慢和混乱的过程。对于解决此问题的其他方法是否有任何建议,也许使用 apply 系列?感谢和抱歉讨厌的代码。

您可以使用 apply 为那些不匹配的值创建索引,然后简单地从一个

中减去它们
idx <- (!apply(df1, 2, function(x) x == df2))
## alternatively, you can use x != df2 too
## idx <- (apply(df1, 2, function(x) x != df2))

df3[idx] <- 1 - df3[idx]
df3

#     V1   V2   V3
# 1 0.25 0.01 0.41
# 2 0.21 0.25 0.75
# 3 0.35 0.35 0.45
# 4 0.75 0.79 0.11

说明

其中 apply 根据 df1 是否匹配 df2

给出 TRUE/FALSE 的矩阵
       V1    V2    V3
[1,] TRUE FALSE  TRUE
[2,] TRUE  TRUE  TRUE
[3,] TRUE FALSE FALSE
[4,] TRUE FALSE  TRUE

因此使用 ! 取反给出相反的值。

!apply(df1, 2, function(x) x == df2)
        V1    V2    V3
[1,] FALSE  TRUE FALSE
[2,] FALSE FALSE FALSE
[3,] FALSE  TRUE  TRUE
[4,] FALSE  TRUE FALSE

然后告诉我们 df 的哪些值我们需要更改

df3[idx]
[1] 0.01 0.35 0.79 0.45

另一种方法是使 df2df1

大小相同
df2  <- cbind(df2, rep( df2, ncol( df1 ) - 1))

df1 != df2