2017-07-17 97 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

相关问题