2017-01-25 8 views
2

Я пытаюсь использовать dplyr для filter мои данные на основе условия тестирования, но это условие проверки может меняться в зависимости от других переменных.R - данные фильтра с dplyr с использованием условия тестирования

Используя встроенный образец набора данных cars:

data(cars) 

Я хотел бы сделать что-то вроде этого:

if (foo == 0) { 
    test <- speed > 15 
} else { 
    test <- dist < 50 
} 
filter(cars, test) 

Это не работает. Я могу заставить его работать, если я изменить его на что-то вроде этого:

if (foo == 0) { 
    test <- 'cars$speed > 15' 
} else { 
    test <- 'cars$dist < 50' 
} 
filter(cars, eval(parse(text = test))) 

Но

  1. Имея в впечатать cars$speed и cars$dist, кажется, поражение цели с помощью функции filter.
  2. Согласно this SO ответьте, используя конструкцию eval(parse(text = ...)) не рекомендуется.

Есть ли лучший способ достичь этого?

ответ

0

Это работает для меня:

library(dplyr) 

if (foo == 0) { 
    test <- cars$speed > 15 
} else { 
    test <- cars$dist < 50 
} 

filter(cars, test) 

Я не вижу проблемы в использовании cars$speed и cars$dist только потому, что вы используете filter. Кроме того, вам действительно нужно использовать filter? Там альтернатива сделать это с помощью базы R. Заменить последнюю строку на:

cars[test,] 
+0

Спасибо! Я согласен с тем, что 'cars [test,]' было бы лучшим решением для этого случая - это был упрощенный пример ради минимального фрагмента кода для вопроса. По какой-то причине это не работало для меня, когда я попытался внедрить это в функцию, которая принимает значение df, column и value и возвращает отфильтрованный набор результатов. Но на самом деле, похоже, сейчас он работает с такой логикой. – Steve

3

Вы можете сделать это:

filter(cars, if(foo==0){speed>15}else{dist<50}) 

испытание путем сравнения с простым фильтром:

> foo =0 
> identical(filter(cars, speed>15), filter(cars, if(foo==0){speed>15}else{dist<50})) 
[1] TRUE 
> foo =1 
> identical(filter(cars, dist<50), filter(cars, if(foo==0){speed>15}else{dist<50})) 
[1] TRUE 

Возможно, было бы проще и аккуратнее поставить оператор filter внутри фигурных скобок:

if (foo == 0) { 
    filter(cars, speed > 15) 
} else { 
    filter(cars, dist < 50) 
} 

Примечание, если вы хотите, чтобы присвоить результат где-то, то if возвращает значение:

> ff = if (foo == 0) { 
     filter(cars, speed > 15) 
    } else { 
     filter(cars, dist < 50) 
    } 
> identical(ff, filter(cars, speed>15)) 
[1] FALSE 
> identical(ff, filter(cars, dist<50)) 
[1] TRUE 
> foo 
[1] 1 
+0

Спасибо! Это приятное решение – Steve

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

  • Нет связанных вопросов^_^