挑战:将数据从Alpha重新编码为非连续数字

时间:2017-11-10 03:39:15

标签: r

我们正在寻找一个快速解决以下问题的解决方案,在R中(允许使用Rcpp)。

我有一个角色矢量:

set.seed(42)
x <- sample(LETTERS[1:4], 1e6, replace = TRUE)

我想将其更改为非连续数字向量,其中:

A = 5
B = 4
C = 3
D = 1

例如:

c("A", "B", "C", "D")

将是:

c(5,4,3,1)

实习生和我已经拥有了我们认为的快速解决方案,但我们认为互联网可以打败我们。在得到一些回复之后,我们将添加我们最快的解决方案作为答案。

让我们看看!

到目前为止的时间:

library(microbenchmark)

set.seed(42)
x <- sample(LETTERS[1:4], 1e6, replace = TRUE)

richscriven <- function(x) {
  as.vector(c(A=5, B=4, C=3, D=2, E=1)[x])
}

richscriven_unname <- function(x) {
  unname(c(A=5, B=4, C=3, D=2, E=1)[x])
}

richscriven_op <- function(x) {
  (5:1)[c(factor(x))]
}

op_and_interns_fun <- function(x) {
  c(5,4,3,1)[as.numeric(as.factor(x))]
}

ronakshah <- function(x) {
  vec = c("A" = 5, "B" = 4, "C" = 3, "D" = 1)
  unname(vec[match(x, names(vec))])
}

microbenchmark(
  richscriven_unname(x),
  richscriven(x),
  richscriven_op(x),
  op_and_interns_fun(x),
  ronakshah(x),
  times = 15
)

Unit: milliseconds
                  expr      min       lq     mean   median       uq       max neval
 richscriven_unname(x) 36.06018 38.01026 62.80854 38.87179 41.86411 337.65773    15
        richscriven(x) 37.90615 41.61194 43.50555 44.14130 45.17277  47.47804    15
     richscriven_op(x) 31.70345 37.43262 44.10522 41.34828 45.22127  88.79605    15
 op_and_interns_fun(x) 40.18935 44.20475 49.48811 45.77867 48.15706  99.85034    15
          ronakshah(x) 29.36408 32.52615 42.40753 35.09052 38.55763  95.78571    15

2 个答案:

答案 0 :(得分:3)

我们可以将矢量放在一个命名的数字向量

vec <-  c("A" = 5, "B" = 4, "C" = 3, "D" = 1)

然后我们可以写一个函数,

get_recoded_data <- function(num_vec, recode_data) {
   unname(recode_data[match(num_vec, names(recode_data))]) 
}

并使用

调用该函数
get_recoded_data(x, vec)

在我的系统上,

system.time(get_recoded_data(x, vec))
#user  system elapsed 
#0.028   0.004   0.032 

我正在使用MacOS Sierra 10.12.6,16GB RAM i7 RStudio 1.1.383

来自@ zacdav的评论使用fmatch包中的fastmatch函数提供了良好的效果提升

get_recoded_data <- function(num_vec, recode_data) {
  unname(recode_data[fmatch(num_vec, names(recode_data))]) 
}

检查相同的数据,我得到了

system.time(get_recoded_data(x, vec))
#user  system elapsed 
#0.017   0.004   0.021 

答案 1 :(得分:1)

我们的答案依赖于一种不太常见的按位置分组的方法:

op_and_interns_fun <- function(x) {
  c(5,4,3,1)[as.numeric(as.factor(x))]
}