2016-07-14 62 views
0

我需要編寫一個函數,數據幀列作爲參數變量,如果其中任何一個丟失了,比如從創建僅在功能參數丟失

foo bar 
1 1 1 
2 2 2 
3 3 3 
4 4 4 
5 5 5 
6 6 6 
7 7 7 
8 8 8 
9 9 9 
10 10 10 

打算將增加新的變量數據框到:

foo bar arg3 
1 1 1 NA 
2 2 2 NA 
3 3 3 NA 
4 4 4 NA 
5 5 5 NA 
6 6 6 NA 
7 7 7 NA 
8 8 8 NA 
9 9 9 NA 
10 10 10 NA 

。到目前爲止,我有這樣的例子:

df <- data.frame(foo = 1:10, bar = 1:10) 

CheckData <- function(data, arg1 = NULL, arg2 = NULL, arg3 = NULL) { 

    list_args <- list(arg1, arg2, arg3) 

    # lapply(list_args, function(x) if(is.null(x)) data[[x]] <<- NA) 
    # lapply(list_args, function(x) if(is.null(x)) data$x <<- NA) 

    return(data) 

} 

CheckData(df, arg1 = 'foo', arg2 = 'bar') 

所以,我傳遞給函數2列,富&酒吧,這使得ARG3是NULL,默認值一個數據幀。在2條註釋掉線,我們有兩個選擇 -

  1. 第一理想地看到,由於arg3list_argsNULL,一個新的變量data[[arg3]]應建立&與NA小號填充。然而,這不起作用,我想知道是否有些非標準評估可以在這裏幫助,以便它不把它看作是NULL對象,而是作爲名稱/字符串。
  2. 第二個以這種方式工作,但創建了一個名爲df$x的變量,而不是df$arg3

我可以明確地做這一個接一個,如

CheckData <- function(data, arg1 = NULL, arg2 = NULL, arg3 = NULL) { 

    if(is.null(arg1)) data$arg1 <- NA 
    if(is.null(arg2)) data$arg2 <- NA 
    if(is.null(arg3)) data$arg3 <- NA  

    return(data) 

} 

CheckData(df, arg1 = 'foo', arg2 = 'bar') 

但這將是不雅,並要求所有可能的變量,這是不是我的需要現實的先驗知識。

這看起來對於高級R程序員來說應該是一個相當直接的問題,但是我被封鎖了,儘管經過了幾個小時的搜索和試驗和錯誤,仍然找不到解決方案。任何幫助

+0

重新閱讀你的問題後,我不完全確定你想完成什麼 - 你想填寫新的列與NA或其他,給定值? –

+0

是的,這正是我想要做的(目前爲NAs)。我想結束一個標準化的數據框,其中包含所有必需的變量/列,以便進行一些標準化分析 –

回答

0

我設法使用plyr包內的一些固有的功能和使用assign,而不是賦值運算符(<-),這讓我的找到一個解決方案有映射到變量的參數名稱,如下圖所示:

library(magrittr) 
dat <- data.frame(foo = 1:10, bar = letters[1:10]) 

CheckData <- function(data, arg1 = NULL, arg2 = NULL, arg3 = NULL, arg4 = NULL) { 

    # create dataframe of missing/unmatched arguments 
    list_args <- 
    list(arg1, arg2, arg3, arg4) %>% 
    setNames(c('arg1', 'arg2', 'arg3', 'arg4')) %>% 
    plyr::ldply(function(x) if(is.null(x)) NA) 

    # create new variables based on these missing arguments; map the arguments to these variables 
    for(i in list_args[[1]]) {data[[i]] <- NA; assign(i, i)} 

    return(data) 

} 

tmp <- CheckData(dat, arg1 = 'foo', arg2 = 'bar') 

這給下面的數據幀,這正是我想要的東西:

foo bar arg3 arg4 
1 1 a NA NA 
2 2 b NA NA 
3 3 c NA NA 
4 4 d NA NA 
5 5 e NA NA 
6 6 f NA NA 
7 7 g NA NA 
8 8 h NA NA 
9 9 i NA NA 
10 10 j NA NA 
1

下非常感謝你想要做什麼:

CheckArgs = function (df, ...) { 
    args = list(...) 
    for (arg in names(args)) { 
     if (! arg %in% names(df)) 
      df[[arg]] = args[[arg]] 
    } 

    df 
} 

或者,下面不相同,但沒有循環:

CheckArgs = function (df, ...) { 
    args = list(...) 
    missing = ! names(args) %in% names(df) 
    df[names(args)[missing]] = args[missing] 
    df 
} 

用法:

df = CheckArgs(df, a = NA, b = NA, c = NA) 

如果你只想填充矢量NA s,那麼更好的解決方案是有一個功能,可以讓你只需指定所需的名字:

df = CheckArgs(df, c('a', 'b', 'c')) 

...或東西沿着這些路線。這當然可以很容易地在幾乎相同的方式來完成:

CheckArgs = function (df, required_names) { 
    missing = ! required_names %in% names(df) 
    df[required_names[missing]] = NA 
    df 
} 
+0

感謝Konrad。然而,如果我需要這個功能,它並不完全工作 - 當調用函數時,會有一些由調用者指定的變量映射 - 例如,在一個實例中,一個數據幀有兩個變量'weight'&'height':'CheckArgs(weightVar ='weight',heightVar ='height')'。假設數據框還需要一個年齡變量('ageVar'),該變量如果存在可以通過'ageVar ='age''匹配,但如果不存在,則不需要在函數調用中指定,但該函數將自動創建一個新的變量'ageVar'並填入NA。這是否更清楚? –