2015-12-09 3 views
8

Я пытаюсь собрать функцию, которая создает подмножество из моего исходного фрейма данных, а затем использует SELECT и MUTATE dplyr, чтобы дать мне количество больших/малых записей на основе сумма ширины и длины чашелистиков/лепестков.Ошибка при использовании dplyr внутри функции

filter <- function (spp, LENGTH, WIDTH) { 
    d <- subset (iris, subset=iris$Species == spp) # This part seems to work just fine 
    large <- d %>%      
    select (LENGTH, WIDTH) %>% # This is where the problem arises. 
    mutate (sum = LENGTH + WIDTH) 
    big_samples <- which(large$sum > 4) 
return (length(big_samples)) 
} 

В принципе, я хочу, чтобы функция возвращала количество больших цветов. Однако, когда я запускаю функцию, я получаю следующую ошибку:

filter("virginica", "Sepal.Length", "Sepal.Width") 

Error: All select() inputs must resolve to integer column positions. 
The following do not: 
* LENGTH 
* WIDTH 

Что я делаю неправильно?

+3

'dplyr' функции нестандартная оценка. Вот почему вам не нужно указывать свои имена переменных, когда вы делаете что-то вроде 'select (mtcars, mpg)' и почему 'select (mtcars," mpg ")' не работает. Когда вы используете функции 'dplyr' в функциях, вы, скорее всего, захотите использовать« стандартную оценку ». Подробнее см. «Виньетка (« nse »)». – ialm

+0

но почему функция? – MLavoie

+2

Быстрое и грязное решение заключается в изменении 'select (LENGTH, WIDTH)%>%' to 'select (get (LENGTH), get (WIDTH))%>%'. Однако вы действительно должны использовать 'select _()' и 'mutate _()' в своих функциях. – ialm

ответ

15

Вы столкнулись с проблемами NSE/SE, см. the vignette for more info.

Вкратце, dplyr использует нестандартную оценку (NSE) имен, а прохождение имен столбцов в функции разбивает его, не используя стандартную версию оценки (SE).

SE-версии функций dplyr заканчиваются на _. Вы можете видеть, что select_ прекрасно работает с вашими оригинальными аргументами.

Однако при использовании функций все усложняется. Мы можем использовать lazyeval::interp преобразовать большинство аргументов функции в имена столбцов, см преобразование вызова в mutate к mutate_ в функции ниже, и в более общем плане, помощь: ?lazyeval::interp

Try:

filter <- function (spp, LENGTH, WIDTH) { 
    d <- subset (iris, subset=iris$Species == spp) 
    large <- d %>%      
     select_(LENGTH, WIDTH) %>% 
     mutate_(sum = lazyeval::interp(~X + Y, X = as.name(LENGTH), Y = as.name(WIDTH))) 
    big_samples <- which(large$sum > 4) 
    return (length(big_samples)) 
} 
+0

Это отличное решение проблемы. Просто из любопытства, может ли кто-нибудь получить более легкую или более простую функцию, которая может быть использована для достижения того же результата? – ari8888

+1

вот что я сделал бы: 'myfun <- function (species, col1, col2) { sum (iris $ Species == species & (iris [[col1]] + iris [[col2]])> 4) } ' – jeremycg

6

UPDATE : С dplyr 0.7.0 вы можете использовать опрятный eval для достижения этого.

Для получения более подробной информации см. http://dplyr.tidyverse.org/articles/programming.html.

filter_big <- function(spp, LENGTH, WIDTH) { 
    LENGTH <- enquo(LENGTH)     # Create quosure 
    WIDTH <- enquo(WIDTH)      # Create quosure 

    iris %>% 
    filter(Species == spp) %>% 
    select(!!LENGTH, !!WIDTH) %>%   # Use !! to unquote the quosure 
    mutate(sum = (!!LENGTH) + (!!WIDTH)) %>% # Use !! to unquote the quosure 
    filter(sum > 4) %>% 
    nrow() 
} 

filter_big("virginica", Sepal.Length, Sepal.Width) 

> filter_big("virginica", Sepal.Length, Sepal.Width) 
[1] 50 
Смежные вопросы