Использовать Саппи или Вектор? - PullRequest
0 голосов
/ 25 января 2019

Я новичок в R, и я нахожу неоднозначным, должен ли я использовать вектор в качестве аргумента для вызова функции или использовать вместо этого sapply для передачи переменных в векторе функции одна за другой.

Разве это не одно и то же?Почему Саппли существует, если это одно и то же?Есть ли случаи, когда я должен использовать тот или иной способ и как узнать, какой способ использовать?

Этот вопрос пришел мне в голову, потому что я писал это

sapply(1:3, function(i) dnorm(i,0,1))

Затем я случайно обнаружил, что могу сделать

dnorm(1:3,0,1)

Как я мог знать это, если бы яслучайно не обнаружил (чтобы не повторить ту же ошибку с другими функциями)?

Обнаружив, что я пытался таким же образом изменить этот код

kappa <- c(1,2,3,4,5,6,7)

sapply(kappa, function(t) 
  optimize(function(x) (t*x^22+5*x+6), c(-10,10))$minimum)

на этот

kappa <- c(1,2,3,4,5,6,7)

  optimize(function(x) (kappa*x^22+5*x+6), c(-10,10))$minimum

но это не сработало!

Пожалуйста, мне нужно хорошее объяснение.

Спасибо

Ответы [ 2 ]

0 голосов
/ 25 января 2019

По сути, sapply и аналогично его родные элементы из семейства apply являются циклами для построения вектора / матрицы или списка из объекта из нескольких элементов. См. Этот канонический ответ по теме: Действительно ли семейство "* apply" не векторизовано? . Однако некоторые операции векторизованы (то есть циклы выполняются на машинном уровне, например в C или Fortran) и могут получать вектор или список и работать в очень быстром времени выполнения.

Почти всегда, зацикленная версия будет работать быстрее. Ниже показаны временные параметры для намного большего ввода последовательности.

system.time({sapply(1:300000, function(i) dnorm(i,0,1))})
#    user  system elapsed 
#   1.097   0.026   1.169

system.time({dnorm(1:300000,0,1)})
#    user  system elapsed 
#   0.006   0.001   0.007

Как вы узнали, dnorm такая векторизованная функция. Многие функции R могут принимать векторы или списки для возврата выходных сигналов одинаковой длины, включая paste, lengths, toupper, [, file.* семейство, as.* семейство, grep семейство. Однако более сложные, многослойные операции требуют итеративных вызовов для возврата отдельных объектов, как вы узнали с помощью optim. Другие не векторизованные методы включают read.csv, write.csv, merge, lm, glm и summary. С помощью таких методов семейство apply может затем итеративно вызывать их и связывать все элементы в единственном объекте, таком как vector / matrix или list.

kappa <- seq(1,7)

sapply(kappa, function(i) optimize(function(x) (i^x^2+5*x+6), c(-10,10))$minimum)
# [1] -9.9999263 -1.2407389 -0.9122106 -0.7784485 -0.7022782 -0.6517733 -0.6151620
0 голосов
/ 25 января 2019

В общем, когда у вас есть вектор, вы всегда должны использовать dnorm(1:3,0,1) -подобный синтаксис вместо sapply.Это просто быстрее и элегантнее.Единственное исключение - когда используемая вами функция не векторизована (на странице справки указано, что аргумент должен быть одним символом / числом, или это ваша собственная функция, которая, как вы знаете, не векторизована).

sapply подходит для списков:

> sapply(list(c(1:5), 5), sum)
[1] 15  5
> sum(list(c(1:5), 5))
Error in sum(list(c(1:5), 5)) : invalid 'type' (list) of argument

и apply для матриц:

> apply(matrix(1:4, 2, 2), 1, sum)
[1] 4 6
> apply(matrix(1:4, 2, 2), 2, sum)
[1] 3 7
> sum(matrix(1:4, 2, 2))
[1] 10

И, как сказал @davide в комментарии, optimize не принимает вектор каквход.

...