Найти элементы даты в столбце Dataframe, которые соответствуют определенному условию в R - PullRequest
0 голосов
/ 30 мая 2018

Я пытаюсь классифицировать экземпляры в кадре данных по Holidays или Normal.

У меня есть даты, которые должны быть классифицированы как Holidays в list/dataframe объекте, и даты, которые я хочуклассифицировать в другом тестовом объекте.

Чтобы быть классифицированным как Holidays, помимо того, что он находится между датами, которые должны быть классифицированы таким образом, в одном из столбцов list/daraframe должно быть Conditionбыть 1 вместо 0 (т. е. экземпляр с датой, которая фактически находится между Holidays, следует пометить как Normal тогда и только тогда, когда соответствующий Condition равен 0).

Объект, содержащий базу данных дней, которые должны быть помечены как Holidays:

holidays2015 <- list(list("2015-01-01",1,1,1),
                     list("2015-01-06",0,1,1),
                     list("2015-03-19",0,1,1),
                     list("2015-04-02",0,1,1),
                     list("2015-04-03",0,1,1),
                     list("2015-05-01",1,1,1),
                     list("2015-05-02",0,1,1),
                     list("2015-05-15",0,1,1),
                     list("2015-06-04",0,1,1),
                     list("2015-08-15",1,1,0),
                     list("2015-10-12",1,1,1),
                     list("2015-11-09",0,1,1),
                     list("2015-12-08",1,1,0),
                     list("2015-12-24",0,0,1),
                     list("2015-12-25",1,1,0),
                     list("2015-12-31",0,0,1))

holidays2014 <- list(list("2014-01-01",1,1,1),
                     list("2014-01-06",0,1,1),
                     list("2014-04-17",0,1,1),
                     list("2014-04-18",0,1,1),
                     list("2014-05-01",1,1,1),
                     list("2014-05-02",0,1,0),
                     list("2014-05-15",0,1,1),
                     list("2014-06-19",0,1,1),
                     list("2014-08-15",1,1,1),
                     list("2014-11-01",1,1,0),
                     list("2014-11-10",0,1,1),
                     list("2014-12-06",1,1,1),
                     list("2014-12-08",1,1,0),
                     list("2014-12-25",1,1,1))
totalholidays <- list(holidays2015, holidays2014)
dfholidays <- lapply(totalholidays, function(x) data.table::rbindlist(x))
dfholidays <- data.table::rbindlist(dfholidays)
names(dfholidays) <- c("Date", "V2", "V3", "Condition")

Даты, которые я хочу пометить:

mytestingdates <- as.data.frame(list("Date" = c("2014-01-07", "2014-08-15", 
"2015-06-04", "2015-08-15")))

Мое рабочее решение для Bucle:

SlowWay

holidaysvector <- c()
for (ii in 1:nrow(mytestingdates)){
  if (mytestingdates$Date[ii] %in% dfholidays$Date){
    tmp <- which(dfholidays$Date == mytestingdates$Date[ii])
    if (dfholidays$Condition[tmp] == 1) {
      holidaysvector <- c(holidaysvector, "Holidays")
    } else { holidaysvector <- c(holidaysvector, "Normal T.1") }
    } else { holidaysvector <- c(holidaysvector, "Normal T.2") }
}
mytestingdates$forsolution <- holidaysvector
rm(tmp)

Но я бы хотел более эффективные решения.Я пробовал некоторые варианты R, но не смог:

R желаемое похожее решение:

mytestingdates$MyRtry <- ifelse(mytestingdates$Date %in% dfholidays$Date, 
ifelse(dfholidays$Condition == 1, "Holiday", "Normal T.1"), "Normal T.2")

Желаемое решение

        Date     MyRtry forsolution
1 2014-01-07 Normal T.2  Normal T.2
2 2014-08-15    Holiday    Holidays
3 2015-06-04    Holiday    Holidays
4 2015-08-15    Holiday  Normal T.1

Обратите внимание, что экземпляр№ 4 находится в Holidays объекте, но его condition равен 0, поэтому он помечен как Normal день, это пропущено в моем решении R.

Любая идея?Любые советы по чистому коду или методам программирования, полученные из моего кода, будут очень оценены.

Ответы [ 2 ]

0 голосов
/ 30 мая 2018

Это решение не различает NormalT1 и NormalT2, но оно довольно простое:

mytestingdates["classifier"] <- ifelse(mytestingdates$Date %in% dfholidays[dfholidays$Condition==1]$Date,"Holiday", "Normal")

mytestingdates

        Date classifier
1 2014-01-07     Normal
2 2014-08-15    Holiday
3 2015-06-04    Holiday
4 2015-08-15     Normal
0 голосов
/ 30 мая 2018

Готовы ли вы к решению dplyr?

library(dplyr)
mytestingdates %>% 
  left_join(dfholidays) %>% 
  mutate(forsolution = ifelse(is.na(Condition), "Normal T.2", ifelse(Condition == 0, "Normal T.1", "Holidays"))) 

Здесь dfholidays присоединяется к mytestingdates.Если дата в mytestingdates не в dfholidays, она объединяет только NA для этих дат.Тогда вы можете проверить, является ли Условие NA, и если это так, вы установите для разрешения значение «Нормальный T.2».Впоследствии вы проверяете, является ли Условие == 0, и если да, вы разрешаете для решения быть "Нормальный T.1".В других случаях решение будет "Праздники".

        Date V2 V3 Condition forsolution
1 2014-01-07 NA NA        NA  Normal T.2
2 2014-08-15  1  1         1    Holidays
3 2015-06-04  0  1         1    Holidays
4 2015-08-15  1  1         0  Normal T.1

ОБНОВЛЕНИЕ: короче будет:

mytestingdates %>% 
  left_join(dfholidays) %>% 
  mutate(forsolution = case_when(is.na(Condition) ~ "Normal T.2", Condition == 0 ~ "Normal T.1",  TRUE ~ "Holidays"))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...