2017-05-25 315 views
0

我想創建一個循環,併爲每個迭代(其數量可以不同的源文件之間)構造一個mutate語句添加一列基於另一個值柱。R:變量使用變量名稱而不是值

有在PHP我的編程背景,在我看來這應該工作:

for(i in number){ 
     colname <- paste("Column",i,sep="") 
     filtercol <- paste("DateDiff_",i,sep="") 
     dataset <- mutate(dataset, a = ifelse(b >= 0 & b <= 364,1,NA)) 
    } 

但是...我已經注意到了幾次,現在有R功能有時函數忽略徹底,你有用這個名字定義一個變量 - as mutate()就在這裏。

因此,我沒有得到幾個標題爲「a1」,「a2」,「a3」等的列,我得到一個標題爲「a」的列,每個迭代都會被覆蓋。首先,有人可以向我指出我在哪裏出錯,但其次有人可以向我解釋在什麼情況下R忽略變量名,因爲它現在已經發生了幾次,而且看起來似乎很不一致這點。我確定它不是,那裏有邏輯,但它確實很好混淆。

另外值得一提的是,原本我想這樣說:

just.dates <- just.dates %>% 
    for(i in number){ 
     a <- paste("a",i,sep="") 
     filtercol <- paste("DateDiff_",i,sep="") 
     mutate(a = ifelse(filtercol >= 0 & filtercol <= 364),1,NA) 
    } 

但這樣決定我經過for()循環4個參數時,它只是想三人。

+0

也許這將幫助:https://stackoverflow.com/questions/26003574/r-dplyr-mutate-use-dynamic-variable-names/26003971#26003971。這個想法是字符串不同於變量。 R中的一些函數使用非標準評估,其中變量被視爲符號名稱,而不是像往常一樣進行評估。另外,當使用命名參數調用函數時,變量永遠不會在等號左邊(參數的名稱)進行評估。 – MrFlick

+0

** a。**頂級版本中的「colname」和「filtercol」有什麼意義? ** b。**如果名稱已經存在,'mutate'將覆蓋列。 ** c。**在R中編寫代碼幾乎總是比for循環更好。在這裏我可以用'purrr :: map_df'製作一個data.frame並使用'bind_cols',但是有很多選項。 ** d。**如果您真的想將字符串變量作爲參數傳遞給dplyr,那麼您需要使用標準評估。 0.5意味着'mutate_'和lazyeval;與即將到來的0.6它意味着[rlang](https://github.com/tidyverse/dplyr/blob/master/vignettes/programming.Rmd)。 – alistaire

+2

和** e。** [您應該讓您的示例可重現。](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example#5963610) – alistaire

回答

0

像這樣的東西可能適合你。與mutate()相反的mutate_()函數可以幫助你解決這個問題。

# Create dataframe for testing 
dataset <- data.frame(date = as.Date(c("06/07/2000","15/09/2000","15/10/2000","03/01/2001","17/03/2001", 
             "06/08/2010","15/09/2010","15/10/2010","03/01/2011","17/03/2011"), "%d/%m/%Y"), 
         event=c(0,0,1,0,1, 1,0,1,0,1), 
         id = c(rep(1,5),rep(2,5)), 
         DateDiff_1 = c(-2,0,34,700,rep(5,6)), 
         DateDiff_2 = c(20,-12,360,900,rep(5,6)) 
        ) 

# Set test number vector 
number <- c(1:2) 

# Begin loop through numbers 
for(i in number){ 
    # Set the name of the new column to be created 
    newcolumn <- paste("Column",i,sep="") 

    # Set the name of the column to be filtered 
    filtercolumn <- paste("DateDiff_",i,sep="") 

    # Create the function to be passed into the mutate command 
    mutate_function = lazyeval::interp(~ ifelse(fc >= 0 & fc <= 364, 1, NA), fc = as.name(filtercolumn)) 

    # Apply the mutate command to the dataframe 
    dataset <- dataset %>% 
       mutate_(.dots = setNames(list(mutate_function), newcolumn)) 
}