2017-07-17 99 views
0

我正在尋找在初始數據幀上多次應用函數。舉個簡單的例子,拿這樣的數據:R:在同一個數據幀上多次運行函數

library(dplyr) 
thisdata <- data.frame(vara = seq(from = 1, to = 20, by = 1) 
         ,varb = seq(from = 1, to = 20, by = 1)) 

這裏是一個簡單的功能,我想在它運行:

simplefunc <- function(data) {datasetfinal2 <- data %>% mutate(varb = varb+1) 
return(datasetfinal2)} 
thisdata2 <- simplefunc(thisdata) 

thisdata3 <- simplefunc(thisdata2) 

所以,我將如何運行這個功能,比如說10倍,而不必保持調用函數(即thisdata3)?我最感興趣的是複製後的最終數據框,但是最好有一個所有生成的數據框的列表,這樣我就可以運行一些診斷。感謝幫助!

回答

2

有多個相同結構的data.frames單獨處理是一個難以駕馭事物的方式,尤其是當迭代次數是多了幾個。一種流行的「最佳實踐」是對付「data.frames的名單」,是這樣的:

n <- 10 # number of times you need to repeat the process 
out <- vector("list", n) 
out[[1]] <- thisdata 
for (i in 2:n) out[[i]] <- simplefunc(out[[i-1]]) 

你可以看一下任何臨時值與

str(out[[10]]) 
# 'data.frame': 20 obs. of 2 variables: 
# $ vara: num 1 2 3 4 5 6 7 8 9 10 ... 
# $ varb: num 10 11 12 13 14 15 16 17 18 19 ... 

,正如你所期望的,最終結果在out[[n]]

這可以稍微用Reduce,並增加了扔掉的第二個參數simplefunc被簡化:

simplefunc <- function(data, ...) { 
    datasetfinal2 <- data %>% mutate(varb = varb+1) 
    return(datasetfinal2) 
} 
out <- Reduce(simplefunc, 1:10, init = thisdata, accumulate = TRUE) 

這有效地做:

tmp <- simplefunc(thisdata, 1) 
tmp <- simplefunc(tmp, 2) 
tmp <- simplefunc(tmp, 3) 
# ... 

(事實上,如果你看一下來源爲Reduce,這實際上是在做我上面的第一條建議。)

請注意,如果simplefunc有一個不能被丟棄,也許其他參數:

simplefunc <- function(data, ..., otherarg, anotherarg) { 
    datasetfinal2 <- data %>% mutate(varb = varb+1) 
    return(datasetfinal2) 
} 

但你必須改變所有其它呼叫simplefunc「按姓名」,而不是通過位置來傳遞參數(這是一種常見的/默認方式)。

編輯:如果你不能(或不願)編輯simplefunc,你總是可以使用匿名函數忽略迭代器/計數器:

Reduce(function(x, ign) simplefunc(x), 1:10, init = thisdata, accumulate = TRUE) 
+0

這可能需要設置一個新問題,但是如何將兩個數據框輸入到reduce函數? (例如在初始點)。 – SlyGrogger

+0

我不清楚你打算做什麼:如果你的意思是分別爲兩個數據框做這件事,那麼就運行兩次(沒有簡單的強大/有彈性的其他方法);如果你的意思是兩個數據框的組合,那麼它取決於你是指'rbind'還是'cbind' -like組合。 – r2evans

+0

對不起,有點難以描述。我在這裏更詳細地概述了這個問題:https://stackoverflow.com/questions/45242969/r-using-reduce-with-custom-function所以大多尋找更多的靈活性,從功能餵養輸出到後續迭代。無論如何,上述答案都很棒。 – SlyGrogger

0

我們可以用一個for循環

thisdata1 <- thisdata 
for(i in 2:3){ 
    assign(paste0('thisdata', i), value = simplefunc(get(paste0('thisdata', i-1)))) 
} 

注1:這是最好不要在全球環境中的操作可以輕鬆地list內完成創建單獨的對象。

NOTE2:忘了添加免責聲明較早

+2

*你知道*它會好得多有一個數據框的列表,而不是使用'assign' ... – r2evans

相關問題