Замените циклы с применением функций семейства (или dplyr), используя логические функции в R

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

df <- data.frame(Date=c("08/29/2011", "08/29/2011", "08/30/2011", "08/30/2011", "08/30/2011", "08/29/2012", "08/29/2012", "01/15/2012", "08/29/2012"),
             Time=c("09:45", "10:00", "13:00", "13:30", "10:14", "9:09", "11:23", "17:06", "12:20"),
             Diff = c(0.2,4.3,6.5,15.0, 16.5, 31, 30.2, 21.9, 1.9))

df1<- df %>%
  mutate(Accuracy=ifelse(Diff<=3, "Excellent", "TBD"))

for(i in 1:nrow(df1)){
  if(df1$Diff[i]>3&&df1$Diff[i]<=10){
    df1$Accuracy[i]<-"Good"} 
  if(df1$Diff[i]>10&&df1$Diff[i]<=15){
    df1$Accuracy[i]<-"Fair"} 
  if(df1$Diff[i]>15&&df1$Diff[i]<=30){
    df1$Accuracy[i]<-"Poor"}
  if(df1$Diff[i]>30){
    df1$Accuracy[i]<-"Unacceptable"}
}

Мой фактический набор данных очень большой, и чтение указывает на то, что циклы, как правило, не самый эффективный способ кодирования в R. Я полагаю, что я могу сделать то же самое, создав логический вектор для каждого условия, и в каждом векторе TRUE - когда каждое условие встретились. Затем я могу присвоить значения путем поднабора, например, df1$Accuracy[Good]<- "Good". Однако я не могу понять, как создать логический вектор, используя функции семейства apply или функции dplyr. (Но любое решение, которое избегает циклов, также приветствуется.) Если циклы for являются лучшим способом, это также было бы полезно знать.

Вот мои неудачные попытки. Они возвращают неверные NA или неверные логические векторы. Одна из многих вещей, которые я не понимаю, это то, как Лэппли знает, как перебирать столбцы или строки.

Good<-apply(df1, 1, function(x) ifelse(df1$Diff[x]>3&& df1$Diff[x]<=10, TRUE, FALSE)) #logical, TRUE where condition is true 
Good<-unlist(lapply(df1$Diff,  function(x) {(ifelse(df1$Diff[x]>3&& df1$Diff[x]<=10, TRUE, FALSE))}))

Обновление: вложенные ifelse заявления будут работать, но любые предложения о том, как использовать применение, все еще приветствуются.

mutate(Accuracy=ifelse(pDiff<=3, "Excellent", 
                         ifelse(pDiff>3&pDiff<=10, "Good",
                                ifelse(pDiff>10&pDiff<=15, "Fair",
                                       ifelse(pDiff>15&pDiff<30, "Poor",
                                              ifelse(Diff>30, "Unpublishable", "TBD"))))))  

1 ответ

Решение

Вы могли бы использовать case_when от dplyr:

df1<- df %>%
mutate(Accuracy= case_when(
  .$Diff <=  3 ~ "Excellent",
  .$Diff <=  10  ~ "Good",
  .$Diff <=  15  ~ "Fair",
  .$Diff <=  30  ~ "Poor",
  .$Diff >   30  ~ "Unpublishable",
  TRUE  ~"TBD")
)

 df1
        Date  Time Diff      Accuracy
1 08/29/2011 09:45  0.2     Excellent
2 08/29/2011 10:00  4.3          Good
3 08/30/2011 13:00  6.5          Good
4 08/30/2011 13:30 15.0          Fair
5 08/30/2011 10:14 16.5          Poor
6 08/29/2012  9:09 31.0 Unpublishable
7 08/29/2012 11:23 30.2 Unpublishable
8 01/15/2012 17:06 21.9          Poor
9 08/29/2012 12:20  1.9     Excellent
Другие вопросы по тегам