我正在使用大型数据集,我们可以将其称为data
,并希望创建新列,然后根据某些列data$results
调用它data$input
。结果基于一些条件if / then逻辑,所以我的原始方法类似于:
for (rows in data) {
data$results <- if(data$results == "1" | data$results== "2") {
trueAnswer
} else {
falseAnswer
}
}
对于大型数据框架,此过程可能需要几个小时才能运行。但是,如果我将数据子集化为仅包含数据$ results为1或2的条目的数据框以及另一个不为真的数据框,我可以将trueAnswer应用于一个数据帧而将falseAnswer应用于另一个数据帧。然后我可以将数据帧重新绑定在一起。这种方法只需要几分钟。
为什么后一种方法使用子集更快?这是一个将此过程应用于许多不同数据集的情况,因此前一种方法太慢而不实用。我只是想了解导致第一种方法缺乏效率的原因。
答案 0 :(得分:0)
始终建议提供fully reproducible & minimal example with sample data。这样我们就可以根据您的样本数据提供具体的帮助。
在很多情况下,R中可以避免使用显式for
循环,而是可以使用优化的矢量化操作。例如ifelse
就是这样的矢量化函数。
通常dplyr
语法是这样的:
library(dplyr);
library(magrittr);
data %>%
mutate(results = ifelse(input == 1 | input == 2, "1 or 2", "Neither 1 nor 2"))
要了解ifelse
如何进行矢量化,请查看?ifelse
。
值:
具有相同长度和属性(包括尺寸)的矢量 和'“class”')作为'test'和来自'yes'值的数据值 或没有'。 [...]
换句话说,如果ifelse
计算100个条件,则返回对象的长度为100.
这可能会导致以下意外/意外结果:
ifelse(c(TRUE), c(100, 200), c(300, 400))
#[1] 100
返回对象是c(100, 200)
的元素1,因为逻辑条件的长度为1。
ifelse(c(TRUE, TRUE, TRUE), c(100, 200), c(300, 400))
#[1] 100 200 100
返回对象的长度为3,因为逻辑条件的长度为3;由于c(100, 200)
只有两个元素,因此R需要回收条目。
答案 1 :(得分:0)
R效率是围绕向量设计的,而不是循环。非常罕见(虽然它确实发生)for或while循环是解决问题的最佳方法。在您的情况下,您最好使用if / else:ifelse的矢量化版本。它需要一个测试向量(例如result %in% 1:2
)和两个可能响应的向量,具体取决于测试结果。所有这些都必须是相同的长度。当您给出长度为1的答案时,它会将其延长到适当的长度,否则会出错。在这里,它看起来像这样:
data$results <- ifelse(results %in% 1:2, trueAnswer, falseAnswer)