用 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
另一种方法是使 df2
与 df1
大小相同
df2 <- cbind(df2, rep( df2, ncol( df1 ) - 1))
df1 != df2
我是 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
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
另一种方法是使 df2
与 df1
df2 <- cbind(df2, rep( df2, ncol( df1 ) - 1))
df1 != df2