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

时间:2017-03-02 21:13:11

标签: r loops apply

我对R来说相对较新,我希望用更有说服力和更快速的东西取代我的凌乱循环(申请?)。基本上,我想基于其他矩阵中相同位置的值是否相互匹配来填充新矩阵。让我来说明一下:

>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。

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

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

例如df1 [1,2] =&#39; G&#39;和df2 [1] =&#39; A&#39;,所以我想要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

当我有大量数据时,这是一个非常缓慢而混乱的过程。有没有其他方法可以解决这个问题,也许使用申请系列?谢谢,抱歉讨厌的代码。

1 个答案:

答案 0 :(得分:1)

您可以使用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