justodd <- function(x) x[ x %% 2 == 1 ]
justodd(4:20)
# [1] 5 7 9 11 13 15 17 19
Пояснение:
Индексация описана в ?Extract
(также в ?[
), вы увидите, что она принимает либо список integer
(или целочисленный numeric
), либо logical
. Если первое, числа должны быть в пределах длины вектора; если последний, то он должен быть той же длины, что и исходный вектор. Например,
x <- 4:20
x[c(3,5,1)]
# [1] 6 8 4
x[c(F,F,T,F,T,F,F,F,T,F,F,F,F,F,F,F,F)]
# [1] 6 8 12
так что наши [
-нутри выглядят как
x %% 2 == 1
# [1] FALSE TRUE FALSE TRUE FALSE TRUE FALSE TRUE FALSE TRUE FALSE TRUE
# [13] FALSE TRUE FALSE TRUE FALSE
затем мы индексируем исходный вектор x
на основе этого возвращаемого значения
Обновление
Ваше упоминание о том, что он не работает с list
в качестве аргумента, предлагает альтернативу, которая является более медленной, но работает как с векторами, так и со списками.
justodd2 <- function(x) Filter(function(a) a %% 2 == 1, x)
vec <- 4:20
lst <- as.list(4:20)
str(vec)
# int [1:17] 4 5 6 7 8 9 10 11 12 13 ...
str(lst)
# List of 17
# $ : int 4
# $ : int 5
# $ : int 6
# $ : int 7
# $ : int 8
# $ : int 9
# $ : int 10
# $ : int 11
# $ : int 12
# $ : int 13
# $ : int 14
# $ : int 15
# $ : int 16
# $ : int 17
# $ : int 18
# $ : int 19
# $ : int 20
justodd2(vec)
# [1] 5 7 9 11 13 15 17 19
justodd2(lst)
# [[1]]
# [1] 5
# [[2]]
# [1] 7
# [[3]]
# [1] 9
# [[4]]
# [1] 11
# [[5]]
# [1] 13
# [[6]]
# [1] 15
# [[7]]
# [1] 17
# [[8]]
# [1] 19
Сравнение производительности:
microbenchmark::microbenchmark(
a = justodd(vec),
b = justodd2(vec),
c = justodd2(lst)
)
# Unit: nanoseconds
# expr min lq mean median uq max neval
# a 800 1000 26642 1100 1200 2537700 100
# b 12100 12500 24154 12700 13150 1055600 100
# c 12100 12300 23777 12500 12800 1022900 100
(Игнорируйте высокие значения mean
и max
от microbenchmark
, они часто смещены при сборке мусора во внутренних органах R. Если вы не знаете, что это такое ... просто нажмите [I believe]
Кнопка или Google.)
Итак, в конечном итоге, если вы всегда имеете дело с векторами, то я предлагаю первое justodd
решение, в противном случае justodd2
безопаснее (так как justodd(lst)
терпит неудачу).