试图在R中对此操作进行矢量化,我不明白为什么这是错误的

时间:2015-06-17 17:58:02

标签: r vectorization apply

如果行中的第2到第4个元素为'ANOMALY',则我想循环遍历数据框并创建一个显示'YES'的新列,否则为'NO'。

for (j in 1:nrow(residual_anomalies)){
  if (all(residual_anomalies[j,2:4]=='ANOMALY')) {residual_anomalies$Prediction_Anomaly[j] <- 'YES'} else
    residual_anomalies$Prediction_Anomaly[j] <- 'NO'
}

所以上面是我正在使用的。它的工作原理但它的计算性能很高,所以我试图对它进行矢量化。到目前为止我所做的是创建一个函数,根据行的元素是否都是“异常”,返回“YES”或“NO”。

vote_for_anomaly <- function(x){
  if (all(x)=='ANOMALY') return('YES') else
    return('NO')}

然后我尝试在R

中使用apply函数
 aggregates <- apply(residual_anomalies[,2:4],1,vote_for_anomaly)

然后我收到以下错误/警告

Error in if (all(x) == "ANOMALY") return("ANOMALY") else return("NO SIGNAL") : 
  missing value where TRUE/FALSE needed
In addition: Warning message:
In all(x) : coercing argument of type 'character' to logical

有人可以告诉我为什么这不起作用以及我该如何改变它?

您可以使用此数据进行测试,并将其称为residual_anomalies

1     ANOMALY     ANOMALY     ANOMALY     ANOMALY
2     ANOMALY     NO SIGNAL     ANOMALY     ANOMALY
3     ANOMALY     ANOMALY     ANOMALY     ANOMALY
4     NO SIGNAL     ANOMALY     NO SIGNAL     ANOMALY
5     ANOMALY     ANOMALY     ANOMALY     ANOMALY
6     NO SIGNAL     NO SIGNAL     ANOMALY     ANOMALY

3 个答案:

答案 0 :(得分:1)

使用索引而不是ifelse()来执行此操作可能会更快。首先设置一个No所需长度的向量:

aggregates <- rep("No", NROW(residual_anomalies))

然后只需将此向量编入索引,其中所有residual_anomalies[, 2:4] == "ANOMALY"

aggregates[rowSums(residual_anomalies[, 2:4] == "ANOMALY") == 3L] <- "Yes"

这给出了:

> aggregates
[1] "Yes" "No"  "Yes" "No"  "Yes" "No"

这部分residual_anomalies[, 2:4] == "ANOMALY"创建了一个逻辑矩阵:

> residual_anomalies[, 2:4] == "ANOMALY"
        V2    V3   V4
[1,]  TRUE  TRUE TRUE
[2,] FALSE  TRUE TRUE
[3,]  TRUE  TRUE TRUE
[4,]  TRUE FALSE TRUE
[5,]  TRUE  TRUE TRUE
[6,] FALSE  TRUE TRUE

当我们选择rowsums()时,TRUE会转换为1FALSE会转换为0。因此,只有那些所有元素都为TRUE的行才会被选中并分配"Yes"

答案 1 :(得分:0)

根据@lukeA,您的代码中存在拼写错误。它应该是

residual_anomalies$Prediction_Anomaly <-
  ifelse(rowSums(residual_anomalies[, 2:4] == "ANOMALY") == 3, "YES", "NO")

但这样做会更快:

filename = fn_downloadname(),

rowSums非常快。

答案 2 :(得分:0)

正如@lukeA所说,你已经混淆了你的括号,但这里也是一个更简单的解决方案:

aggregates <- ifelse(apply(residual_anomalies, 1, 
     function(x) all(x[2:4] == "ANOMALY")), "YES", "NO")