2017-02-18 37 views
0

我想用一些可選參數編​​寫R函數。它應該通過兩個核心參數對一些數據進行子集分類,然後我希望可以選擇傳遞額外的約束條件。例如。具有可選通配符參數的R子集自定義函數

filter_func <- function(start_datetime, end_datetime, user=*, type=*){ 
    as.data.frame(subset(df, format(df$datetime,"%Y-%m-%d %H:%M:%S") > start_datetime & 
          format(df$datetime,"%Y-%m-%d %H:%M:%S") < end_datetime) & 
          df$user == user & 
          df$type == type) 

所以......如果我通過一個PARAM它,它限制對用戶或類型的列,但如果我不它使用通配符和列得到的一切?

我見過這裏的例子使用%in%grepl()但這些似乎更多旨在那就是你有一個字符串的一部分,然後想休息...像new_york變得既new_york_citynew_york_state ......我不想要獲得任何與param不完全匹配的值!

編輯:現在的例子

所以......從這樣的理想去...

start   |  end  | user | type | 
-----------------|------------------|------|------| 
2017-01-01 11:00 | 2017-01-01 20:00 | usr1 | typ1 | 
2017-01-01 12:00 | 2017-01-01 19:00 | usr2 | typ2 | 
2017-01-01 02:00 | 2017-01-01 03:00 | usr2 | typ1 | 
2017-03-01 01:00 | 2017-03-01 09:00 | usr1 | typ2 | 
2017-04-01 05:00 | 2017-04-01 07:00 | usr3 | typ4 | 
2017-05-01 01:00 | 2017-05-01 08:00 | usr2 | typ5 | 

用我的功能filter_func(2017-01-01 00:00, 2017-01-01 23:59)

打動了我:

start   |  end  | user | type | 
-----------------|------------------|------|------| 
2017-01-01 11:00 | 2017-01-01 20:00 | usr1 | typ1 | 
2017-01-01 12:00 | 2017-01-01 19:00 | usr2 | typ2 | 
2017-01-01 02:00 | 2017-01-01 03:00 | usr2 | typ1 | 

但如果我添加一個PARAM filter_func(2017-01-01 00:00, 2017-01-01 23:59, usr2)

start   |  end  | user | type | 
-----------------|------------------|------|------| 
2017-01-01 12:00 | 2017-01-01 19:00 | usr2 | typ2 | 
2017-01-01 02:00 | 2017-01-01 03:00 | usr2 | typ1 | 

甚至filter_func(2017-01-01 00:00, 2017-01-01 23:59, usr2, typ2)

start   |  end  | user | type | 
-----------------|------------------|------|------| 
2017-01-01 12:00 | 2017-01-01 19:00 | usr2 | typ2 | 
+0

使用單詞邊界,即'在年底\\ B' – akrun

+1

可能會幫忙看看樣本數據和預期結果 – Bulat

+0

@akrun,您能否提供更多示例?正如我在做'user ='\\ b''? – Huw

回答

1

首先,

  • [是不是subset編程使用更安全。
  • 您不需要format,它將日期時間對象轉換爲字符串;您需要as.POSIXct或類似的東西,它將字符串解析爲日期時間。你可以在函數中做到這一點,但你應該之前做這個功能,因爲你總是希望你的日期時間分析,並沒有重複做這件事。
  • 您可以通過多個步驟更新函數內部的data.frame版本,從而允許您使用控制流,如if。你仍然需要檢查變量是否存在。兩種選擇:
    • 使用missing,它是爲檢查函數參數是否存在而構建的。
    • 提供默認值NULL並使用is.null
  • 您需要傳遞帶引號的字符串或解析的日期時間(<運算符將嘗試強迫與同一類不匹配的對象)。
  • 我添加了一個參數,首先傳入data.frame,這使得函數具有更廣泛的用途,但沒有必要。

總之,然後,

df <- data.frame(start = c("2017-01-01 11:00", "2017-01-01 12:00", "2017-01-01 02:00", 
          "2017-03-01 01:00", "2017-04-01 05:00", "2017-05-01 01:00"), 
       end = c("2017-01-01 20:00", "2017-01-01 19:00", "2017-01-01 03:00", 
         "2017-03-01 09:00", "2017-04-01 07:00", "2017-05-01 08:00"), 
       user = c("usr1", "usr2", "usr2", "usr1", "usr3", "usr2"), 
       type = c("typ1", "typ2", "typ1", "typ2", "typ4", "typ5")) 

# parse in two steps if you like, e.g. df$start <- as.POSIXct(df$start) 
df[1:2] <- lapply(df[1:2], as.POSIXct) 

filter_func <- function(x, start_time, end_time, usr, typ = NULL){ 
    x <- x[x$start > start_time & x$end < end_time, ] 
    if (!missing(usr)) { 
     x <- x[x$user %in% usr, ] 
    } 
    if (!is.null(typ)) { 
     x <- x[x$type %in% typ, ] 
    } 
    x 
} 

並對其進行測試:

str(df) 
#> 'data.frame': 6 obs. of 4 variables: 
#> $ start: POSIXct, format: "2017-01-01 11:00:00" "2017-01-01 12:00:00" ... 
#> $ end : POSIXct, format: "2017-01-01 20:00:00" "2017-01-01 19:00:00" ... 
#> $ user : Factor w/ 3 levels "usr1","usr2",..: 1 2 2 1 3 2 
#> $ type : Factor w/ 4 levels "typ1","typ2",..: 1 2 1 2 3 4 

filter_func(df, as.POSIXct('2017-01-01 00:00'), as.POSIXct('2017-01-01 23:59')) 
#>     start     end user type 
#> 1 2017-01-01 11:00:00 2017-01-01 20:00:00 usr1 typ1 
#> 2 2017-01-01 12:00:00 2017-01-01 19:00:00 usr2 typ2 
#> 3 2017-01-01 02:00:00 2017-01-01 03:00:00 usr2 typ1 

filter_func(df, '2017-01-01 00:00', '2017-01-01 23:59') 
#>     start     end user type 
#> 1 2017-01-01 11:00:00 2017-01-01 20:00:00 usr1 typ1 
#> 2 2017-01-01 12:00:00 2017-01-01 19:00:00 usr2 typ2 
#> 3 2017-01-01 02:00:00 2017-01-01 03:00:00 usr2 typ1 

filter_func(df, '2017-01-01 00:00', '2017-01-01 23:59', 'usr2') 
#>     start     end user type 
#> 2 2017-01-01 12:00:00 2017-01-01 19:00:00 usr2 typ2 
#> 3 2017-01-01 02:00:00 2017-01-01 03:00:00 usr2 typ1 

filter_func(df, '2017-01-01 00:00', '2017-01-01 23:59', 'usr2', 'typ2') 
#>     start     end user type 
#> 2 2017-01-01 12:00:00 2017-01-01 19:00:00 usr2 typ2 
1

您需要使用grepl()模式匹配。

filter_func <- function(start_datetime, end_datetime, user_='*', type_='*'){ 
    subset(df, as.POSIXlt(df$start) > as.POSIXlt(start_datetime) & 
          as.POSIXlt(df$end) < as.POSIXlt(end_datetime) & 
          grepl(user_, df$user) & 
          grepl(type_, df$type)) 
} 

filter_func(start='2017-01-01 00:00', end='2017-01-01 23:59') 
#   start    end user type 
#1 2017-01-01 11:00 2017-01-01 20:00 usr1 typ1 
#2 2017-01-01 12:00 2017-01-01 19:00 usr2 typ2 
#3 2017-01-01 02:00 2017-01-01 03:00 usr2 typ1 

filter_func(start='2017-01-01 00:00', end='2017-01-01 23:59', user='usr2') 
#   start    end user type 
#2 2017-01-01 12:00 2017-01-01 19:00 usr2 typ2 
#3 2017-01-01 02:00 2017-01-01 03:00 usr2 typ1 

filter_func(start='2017-01-01 00:00', end='2017-01-01 23:59', user='usr2', type='typ2') 
#   start    end user type 
#2 2017-01-01 12:00 2017-01-01 19:00 usr2 typ2 
相關問題