Есть ли более быстрый метод, который создает вектор с заданным режимом и длиной, заполненной только значениями NA - PullRequest
1 голос
/ 17 марта 2019

Мне нужно создать вектор с заданным режимом и длиной. Я использую этот код, который работает:

NA_vec<-function(vec_mode, vec_length)
{
  vec<-vector(mode=vec_mode, length=vec_length)
  vec<-replace(vec, vec==0, NA)
  return(vec)
}

a<-NA_vec("numeric", 20)

Вопрос: Есть ли более быстрый способ сделать то же самое?


Edit1:

Еще одна медленная версия, но я думаю, что будет работать с любым режимом:

NA_vec5 = function(vec_mode, vec_length)
{
  vec<-vector(mode=vec_mode, length=vec_length)
  for (i in 1:length(vec))
  {
    vec[i]<-NA
  }
  return(vec)
}

Benchmark:

n = 1e5
microbenchmark::microbenchmark(
  DJJ=NA_vec4("numeric", n),
  Gregor = NA_vec3("numeric", n),
  G5W = NA_vec2("numeric", n),
  OP = NA_vec("numeric", n),
  OP_with_for = NA_vec5("numeric", n)

)

Результат теста:

Unit: microseconds
        expr      min        lq      mean    median        uq       max neval  cld
         DJJ  269.213  348.7520  489.1965  382.3055  424.9365 10240.310   100 a   
      Gregor  351.713  430.0685  578.2138  475.4635  542.7665  8784.119   100 a   
         G5W 1051.979 1207.5065 1588.2552 1271.6510 1364.6125 24294.583   100  b  
          OP 1537.902 1776.1270 2732.4603 1934.4170 2101.9840 26363.014   100   c 
 OP_with_for 5772.263 6065.1595 6473.3508 6196.4100 6376.8055 11310.446   100    d

Ответы [ 3 ]

6 голосов
/ 17 марта 2019

Используйте соответствующий тип NA напрямую:

NA_vec3 = function(mode, length) {
  mode = match.arg(mode, choices = c("numeric", "integer", "complex", "logical", "character"))
  if (mode == "numeric") return(rep(NA_real_, length))
  if (mode == "integer") return(rep(NA_integer_, length))
  if (mode == "complex") return(rep(NA_complex_, length))
  if (mode == "character") return(rep(NA_character_, length))
  rep(NA, length)
}

n = 1e5
microbenchmark::microbenchmark(
  Gregor = NA_vec3("numeric", n),
  G5W = NA_vec2("numeric", n),
  OP = NA_vec("numeric", n)
)
# Unit: microseconds
#    expr     min        lq      mean    median        uq       max neval
#  Gregor 210.160  224.4410  343.2125  244.5395  271.3385  7749.094   100
#     G5W 644.583  670.8525 1280.5191  683.7235  705.5860 11864.828   100
#      OP 995.436 1021.7055 2020.2795 1051.8545 1346.6415 12450.877   100

Для исторического интереса этот ответ был удален:

NA_vec2<-function(vec_mode, vec_length) {
  vec<-vector(mode=vec_mode, length=vec_length)
  vec<-replace(vec, 1:vec_length, NA)
}

Как еще одна идея, я тоже попробовал это, но это было даже медленнее, чем оригинал, поэтому я пропустил это.

# slowest yet
NA_vec4 = function(mode, length) {
  x = rep(NA, length)
  storage.mode(x) = mode
  x
}
4 голосов
/ 17 марта 2019

Немного быстрее с matrix вместо rep

NA_vec3 = function(mode, length) {
  mode = match.arg(mode, choices = c("numeric", "integer", "complex", "logical", "character"))
  if (mode == "numeric") return(rep(NA_real_, length))
  if (mode == "integer") return(rep(NA_integer_, length))
  if (mode == "complex") return(rep(NA_complex_, length))
  if (mode == "character") return(rep(NA_character_, length))
  rep(NA, length)
}



NA_vec4 = function(mode, length) {
  mode = match.arg(mode, choices = c("numeric", "integer", "complex", "logical", "character"))

  if (mode == "numeric") return(matrix(NA_real_, nrow=length))
  if (mode == "integer") return(matrix(NA_integer_, nrow=length))
  if (mode == "complex") return(matrix(NA_complex_, nrowlength))
  if (mode == "character") return(matrix(NA_character_, nrow=length))
  matrix(NA, nrow=length)
  }

n = 1e5
microbenchmark::microbenchmark(
  Gregor = NA_vec3("numeric", n),
  DJJ=NA_vec4("numeric", n)
  )


# Unit: microseconds
#    expr     min      lq     mean   median      uq      max neval
#  Gregor 295.499 755.858 978.8608 768.0445 803.245 10907.67   100
#     DJJ 245.842 590.997 824.9774 603.2195 635.591 10660.85   100
1 голос
/ 18 марта 2019

Вы можете инициировать ваш вектор с нулевой длиной, а затем присвоить ему необходимую длину, он будет содержать NA s соответствующего типа:

NA_vec <- function(vec_mode, vec_length) `length<-`(vec_mode(), vec_length) 

Примеры:

NA_vec (integer,5)
# [1] NA NA NA NA NA
typeof(.Last.value)
# [1] "integer"
NA_vec(character,5)
# [1] NA NA NA NA NA
typeof(.Last.value)
# [1] "character"

Это также быстрее, чем текущие самые быстрые альтернативы:

n = 1e5
microbenchmark::microbenchmark(
  mm = NA_vec(numeric, n),
  Gregor = NA_vec3("numeric", n),
  DJJ = NA_vec4("numeric", n)
)
# Unit: microseconds
#    expr   min     lq    mean median     uq     max neval cld
#      mm 204.4 241.55 268.680 263.25 285.00   472.0   100   a
#  Gregor 232.4 288.80 432.043 300.20 334.15 12499.1   100   a
#     DJJ 174.4 205.40 548.774 219.20 238.10 11456.3   100   a
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...