Как отфильтровать фрейм данных по датам в столбце, хранящемся в переменной? - PullRequest
0 голосов
/ 02 августа 2020

Я пишу функцию R, которая должна принимать входные данные, у которых есть любой тип столбца с датами в нем. И поэтому на основе этого столбца я должен затем отфильтровать все эти данные, чтобы они возвращали данные между определенными c датами.

Проблема в том, что теоретически я не могу смотреть на эти данные и то, что имя столбца, в котором хранится эта дата, поэтому я сначала нахожу этот столбец и могу сохранить в какой-то переменной.

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

(date_check - это условие для проверки того, существуют ли даты и имеют ли они правильную форму, и оно отлично работает)

cols <- colnames(select_if(input.data, date_check == TRUE))
names(input.data)[names(input.data) == cols] <- dates.column.name

date_check <- sapply(input.data, function(x) !all(is.na(as.Date(as.character(x),format="%Y-%m-%d"))))

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

modifier <- function(input.data, dates.column.name = "Date") {
  date_check <- sapply(input.data, function(x) !all(is.na(as.Date(as.character(x),format="%Y-%m-%d"))))
  if (missing(dates.column.name)) {
    cols <- colnames(select_if(input.data, date_check == TRUE))
    names(input.data)[names(input.data) == cols]  <- "Date"
  } else {
    cols <- colnames(select_if(input.data, date_check == TRUE))
    names(input.data)[names(input.data) == cols] <- dates.column.name
  } 
  if (missing(dates.column.name)) {
    input.data$Date <- as.Date(input.data$Date, format= "%Y-%m-%d")
    input.data <- filter(input.data, Date < "2014-12-12" & Date > "2013-01-01")
  } else {
    input.data[, dates.column.name] <- as.Date(input.data[, dates.column.name], format= "%Y-%m-%d")
    input.data <- input.data[(input.data$dates.column.name> "2012-12-03" && input.data$dates.column.name < "2014-12-05"),]
  }
  input.data
}

Может ли кто-нибудь помочь мне, как я могу получить доступ к этому столбцу, чтобы иметь возможность фильтровать его даты?

Если я передам небольшой фрейм данных и дам ему второй аргумент по умолчанию, он будет выглядеть примерно так. Исходные данные:

 Row.ID        Order.ID  Ship.Date    Ship.Mode
1  32298  CA-2012-124891 2012-07-31     Same Day
2  26341   IN-2013-77878 2013-02-07 Second Class
3  25330   IN-2013-71249 2013-10-18  First Class
4  13524 ES-2013-1579342 2013-01-30  First Class
5  47221    SG-2013-4320 2013-11-06     Same Day
6  22732   IN-2013-42360 2013-07-01 Second Class
modifier(exam_data)

Вывод:

Row.ID        Order.ID       Date    Ship.Mode
1  26341   IN-2013-77878 2013-02-07 Second Class
2  25330   IN-2013-71249 2013-10-18  First Class
3  13524 ES-2013-1579342 2013-01-30  First Class
4  47221    SG-2013-4320 2013-11-06     Same Day
5  22732   IN-2013-42360 2013-07-01 Second Class

Но если я дам ему второй аргумент, это будет выглядеть так:

modifier(exam_data, dates.column.name = "XXX")

 Row.ID Order.ID  XXX Ship.Mode
NA       NA     <NA> <NA>      <NA>
NA.1     NA     <NA> <NA>      <NA>
NA.2     NA     <NA> <NA>      <NA>
NA.3     NA     <NA> <NA>      <NA>
NA.4     NA     <NA> <NA>      <NA>
NA.5     NA     <NA> <NA>      <NA>

1 Ответ

0 голосов
/ 02 августа 2020

Здесь мы могли бы преобразовать имя столбца в символ с помощью ensym (что также будет работать, если имя столбца будет передано без кавычек) и оценить (!!)

modifier <- function(input.data, dates.column.name = "Date") {
      
    # // convert to a symbol
    # // can also convert unquoted argument to symbol
    datecolumn <- rlang::ensym(dates.column.name)
    if(missing(dates.column.name)) { # // => evaluates if no date argument
       input.data %>%
          # // General : matches substring of column name
          # //         : can apply to more than one column  
           mutate(across(ends_with('Date'),
                  ~ as.Date(., '%Y-%m-%d'))) %>%
          # // General : matches substring of column name
                       : can apply to more than one column
         filter(across(ends_with('Date'), 
               ~ . < "2014-12-12" & . > "2013-01-01"))
      
      } else {
        input.data %>%
            # // evaluates the rhs of assignment operator (:=)
            # // assigns to evaluation of the string converted symbol
            mutate(!! rlang::as_name(datecolumn) :=
                     as.Date(!! datecolumn, '%Y-%m-%d')) %>%
            filter(!! datecolumn > "2012-12-03" & 
                   !! datecolumn < "2014-12-05")
      
      
      }
 

}

-testing

modifier(exam_data) # // no arguments for dates.column.name, missing => TRUE
  Row.ID        Order.ID  Ship.Date    Ship.Mode
1  26341   IN-2013-77878 2013-02-07 Second Class
2  25330   IN-2013-71249 2013-10-18  First Class
3  13524 ES-2013-1579342 2013-01-30  First Class
4  47221    SG-2013-4320 2013-11-06     Same Day
5  22732   IN-2013-42360 2013-07-01 Second Class

modifier(exam_data, dates.column.name = Ship.Date) # // unquoted dates column  name
  Row.ID        Order.ID  Ship.Date    Ship.Mode
1  26341   IN-2013-77878 2013-02-07 Second Class
2  25330   IN-2013-71249 2013-10-18  First Class
3  13524 ES-2013-1579342 2013-01-30  First Class
4  47221    SG-2013-4320 2013-11-06     Same Day
5  22732   IN-2013-42360 2013-07-01 Second Class
 
modifier(exam_data, dates.column.name = "Ship.Date") # // quoted dates column name
  Row.ID        Order.ID  Ship.Date    Ship.Mode
1  26341   IN-2013-77878 2013-02-07 Second Class
2  25330   IN-2013-71249 2013-10-18  First Class
3  13524 ES-2013-1579342 2013-01-30  First Class
4  47221    SG-2013-4320 2013-11-06     Same Day
5  22732   IN-2013-42360 2013-07-01 Second Class
...