Запутался в функции vapply, использующей grepl внутри (часть курса datacamp)

hits <- vapply(titles,
           FUN = grepl,
           FUN.VALUE = logical(length(pass_names)),
           pass_names)

titles — это вектор с такими заголовками, как "mr", pass_names — это список имен.

2 вопроса.

  1. Я не понимаю результирующие хиты матрицы
  2. Я не понимаю, почему последняя строка pass_names и как я должен знать об этих 4 аргументах. Под ?vapply указаны x, FUN, FUN.VALUE, но я не могу понять, как я должен понять, что pass_names должен быть указан там.

Я искал в Интернете и не смог найти ответ, поэтому я надеюсь, что это поможет и другим. Заранее спасибо за ответы, да я новичок.


Дополнительная информация: в этом вопросе используется титанический пакет в R, pass_names — это просто titanic$Name, titles — это просто paste(",", c("Mr\\.", "Master", "Don", "Rev", "Dr\\.", "Major", "Sir", "Col", "Capt", "Jonkheer")).


person Alexis Drakopoulos    schedule 13.02.2018    source источник


Ответы (2)


Вы правы, что немного сбиты с толку.

Фрагмент кода vapply в вашем вопросе эквивалентен:

hits <- vapply(titles,
               FUN = function(x) grepl(x, pass_names),
               FUN.VALUE = logical(length(pass_names)))

vapply принимает аргумент ..., который принимает столько аргументов, сколько предусмотрено. Если аргументы не названы (см. комментарий @Roland), n-й аргумент в позиции ... передается n+1-му аргументу FUN (первым аргументом FUN является X, т.е. titles в данном случае).

Результирующая матрица имеет то же количество строк, что и количество строк в titanic, и имеет 10 столбцов длиной titles. [i, j]-я запись равна TRUE, если ipass_names соответствует j-му регулярному выражению в titles, FALSE — если нет.

person Hugh    schedule 13.02.2018
comment
Функции *apply могут выполнять сопоставление имен для аргументов в .... Поэтому X не должен быть первым аргументом; например, lapply(1:4, matrix, data = 1) работает. - person Roland; 13.02.2018
comment
Из решения этого вопроса для меня совершенно очевидно, что я просто не понимаю, как вообще работают эти функции. Позвольте мне попытаться увидеть, правильно ли я понял это. - person Alexis Drakopoulos; 13.02.2018

По сути, вы передаете два вектора в свой vapply, что эквивалентно двум вложенным циклам for. Каждая пара затем передается в обязательные аргументы grepl: grepl(pattern, x).

В частности, в первом цикле vapply первый элемент в titles сравнивается с каждым элементом в pass_names. Затем во втором цикле второй элемент в titles снова сравнивается со всеми элементами pass_names и так далее, пока первый вектор, titles, не будет исчерпан. .

Чтобы проиллюстрировать это, вы можете аналогичным образом построить матрицу hits2, используя вложенные for циклы, отображая точно так же, как ваши выходные данные vapply, hits:

hits2 <- matrix(NA, nrow=length(df$name), ncol=length(titles))
colnames(hits2) <- titles

for (i in seq_along(df$name)) {

  for (j in seq_along(titles)) {

    hits2[i, j] <- grepl(pattern=titles[j], x=df$name[i])

  }

}

all.equal(hits, hits2)
# [1] TRUE

В качестве альтернативы вы можете запустить то же самое в sapply без обязательного аргумента FUN.VALUE, поскольку и sapply, и vapply являются оболочками для lapply. Тем не менее, vapply предпочтительнее, так как вы активно заявляете о своем выводе, в то время как sapply выполняет рендеринг одним способом в зависимости от функции. Например, в vapply вы можете отобразить целочисленную матрицу с помощью: FUN.VALUE = integer(length(pass_names)).

hits3 <- sapply(titles, FUN = grepl, pass_names)

all.equal(hits, hits3)
# [1] TRUE

В целом, семейство apply — это более лаконичные и компактные способы запуска итераций и визуализации структуры данных вместо инициализации и назначения вектора/матрицы с for или while циклами.

Для дальнейшего чтения рассмотрим этот интересный пост SO: Действительно ли не векторизован?

person Parfait    schedule 13.02.2018