2016-11-01 2 views
0

Я зацикливаю на оценке и сохраняю все объекты оценки, а затем выбираю тот, у кого самое низкое отклонение. Для этого я хотел использовать функции Filter/Map/Position, но я не мог найти решение, потому что он всегда возвращает первый объект списка, а не второй. Я, вероятно, неправильно понимаю, как работает функция Position, но хотелось бы знать, что я пропустил.Функция более высокого порядка найти мин. Списка

MWE:

ls<-list(3,2,4) 
Position(min,Map(function(x) {x^2}, ls)) 

Я закончил с использованием unlist и which.min

ответ

1

Вы в конечном итоге делает правильную процедуру. Зачем? Во-первых, мы будем тянуть выделяющейся выписку из страницы справки:

Position(f, x, right = FALSE, nomatch = NA_integer_)

Find и Position по образцу Common Lisp находят, если и позиционно-если, соответственно. Если есть элемент, для которого функция предиката дает true, тогда возвращается первый или последний такой элемент или его позиция в зависимости от того, правильно ли установлено значение false (по умолчанию) или true. Если такого элемента нет, возвращается значение, указанное в nomatch. Текущая реализация не оптимизирована для производительности.

Так, Position() собирается применить f() ко всем элементам x и когда результат f() является TRUE (непосредственно или через принуждение) Position() возвращает индекс этого элемента (если ничего не заканчивает тем, что TRUE то он возвращает значение, присвоенное nomatch).

Вот фактический источник Position() функция:

Position <- function (f, x, right=FALSE, nomatch=NA_integer_) { 

    ind <- seq_along(x) 
    if (right) ind <- rev(ind) 

    for (i in ind) { 
    if (f(x[[i]])) return(i) 
    } 

    nomatch 

} 

После источника вы можете prbly увидеть, что min() становится называется на первый элемент списка и возвращает значение, которое min() вектора в списке позиция 1, и это значение не равно нулю, поэтому он считает, что он сделал хорошую работу и возвращает индекс списка, в котором он был.

Если вы делали:

Position(min, Map(function(x) {x-3}, dat)) 

, то вы увидели бы результат быть:

## [1] 2 

и, возможно, думал, что это работает, но это возвращает только, что с первого элемента из списка 3 и 3-3 == 0 и 0 принуждаются к FALSE.

ПРИМЕЧАНИЕ: ls - это также имя базовой функции, которая является прекрасной, так как R знает, что делать на основе контекста использования, но мне не нравится потенциально вызывать странные ошибки в дороге в вызовах функций, разбивая очень общее пространство имен элементов, поэтому я использовал dat вместо ls.

Идея Position() больше что-то вроде:

eqls4 <- function(x) x==4 

Position(eqls4, Map(function(x) {x^2}, dat)) 

который делает возвращение:

## [1] 2 

Итак, что вы в конечном итоге делает был 100% правильно.

Следует также отметить, что purrr пакета предоставляет альтернативные функциональные идиомы, что (ИМО), имеет тенденцию быть более читаемыми + есть способы обеспечения надлежащих типов поддерживаются и экспортирует %>% так трубопроводы также легко доступны:

library(purrr) 

map(dat, ~.^2) %>% 
    flatten_dbl() %>% 
    which.min() 
+0

Thx для обширного ответа. Но это сводится к тому, что я использую неправильный подход, потому что функция min применяется к каждому элементу списка моего списка, и это возвращает [[1]], если это не сработает, как в вашем примере. Таким образом, использование списка и т. Д. Является правильным подходом? –

+0

правый. 'flatten_dbl()' является "purrr'" безопасной "версией' unlist' (т. е. всегда будет возвращать вектор «double's vs, возможно, вектор символов»). – hrbrmstr

+0

Thx, мне было просто любопытно и на самом деле неправильно поняли сферу применения и функцию Position. Но, возможно, это помогает другим людям :) –

Смежные вопросы