使用DF <- iris[-5] 作为样本数据,您可以使用cut,正如我在 cmets 中建议的那样。
试试:
DF[] <- lapply(DF, cut, c(-Inf, -2, 2, Inf), c("down", "no_change", "up"))
head(DF)
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## 1 up up no_change no_change
## 2 up up no_change no_change
## 3 up up no_change no_change
## 4 up up no_change no_change
## 5 up up no_change no_change
## 6 up up no_change no_change
tail(DF)
## Sepal.Length Sepal.Width Petal.Length Petal.Width
## 145 up up up up
## 146 up up up up
## 147 up up up no_change
## 148 up up up no_change
## 149 up up up up
## 150 up up up no_change
或者,使用 RHertel 的“mock_data”:
cut(mock_data, c(-Inf, -2, 2, Inf), c("down", "no_change", "up"))
## [1] no_change no_change no_change down up up down
## [8] down up no_change no_change up no_change no_change
## [15] up
## Levels: down no_change up
基准测试
正如我在 cmets 中所建议的,RHertel 的方法可能是最有效的。该方法使用非常简单的子集(速度很快)和factor(通常也很快)。
在您描述的数据大小上,您肯定会注意到差异:
set.seed(1)
nrow = 20000
ncol = 1000
x <- as.data.frame(matrix(runif(nrow * ncol, min=-5, max=5), ncol = ncol))
factorize <- function(invec) {
factorized <- rep("no_change", length(invec))
factorized[invec > 2] <- "up"
factorized[invec < -2] <- "down"
factor(factorized, c("down", "no_change", "up"))
}
RHfun <- function(indf = x) {
indf[] <- lapply(indf, factorize)
indf
}
AMfun <- function(DF = x) {
DF[] <- lapply(DF, cut, c(-Inf, -2, 2, Inf), c("down", "no_change", "up"))
DF
}
library(microbenchmark)
microbenchmark(AMfun(), RHfun(), times = 10)
# Unit: seconds
# expr min lq mean median uq max neval
# AMfun() 7.501814 8.015532 8.852863 8.731638 9.660191 10.198983 10
# RHfun() 1.437696 1.485791 1.723402 1.574507 1.637139 2.528574 10