在数据框列表上循环应用功能

罗斯

我浏览了各个带有类似问题(有些链接)的“溢出”页面,但没有发现任何似乎可以帮助完成此复杂任务的内容。

我的工作区中有一系列数据框,我想在所有这些框上循环使用相同的功能(rollmean或该功能的某些版本),然后将结果保存到新的数据框中。

我写了几行代码来生成所有数据帧的列表和一个for循环,该循环应在每个数据帧上迭代一条apply语句;但是,在尝试完成我希望实现的所有功能时遇到了问题(下面包含了我的代码和一些示例数据):

1)我想将rollmean函数限制为除第一列(或前几列)以外的所有列,以使列“ info”不会平均。我还想将此列添加回输出数据框中。

2)我想将输出另存为新的数据框(具有唯一的名称)。我不在乎是将其保存到工作区还是以xlsx格式导出,因为我已经编写了批量导入代码。

3)理想情况下,我希望结果数据框与输入的观察数相同,以rollmean缩小您的数据。我也不想这些成为NA,所以我不希望使用fill = NA 这可以通过写一个新的功能,传递来完成type = "partial"rollmean(尽管仍然由1缩小在我手里我的数据),或开始侧倾平均在第n + 2项上进行运算,并将非平均的nth和nth + 1项绑定到结果数据帧。任何方式都可以。(有关详细信息,请参见图片,它说明了后者的外观)

我的代码只能完成其中的一部分,并且无法使for循环协同工作,但是如果我在单个数据帧上运行它们,则可以使部分工作。

非常感谢任何输入,因为我没有主意。

#reproducible data frames 
a = as.data.frame(cbind(info = 1:10, matrix(rexp(200), 10)))
b = as.data.frame(cbind(info = 1:10, matrix(rexp(200), 10)))
c = as.data.frame(cbind(info = 1:10, matrix(rexp(200), 10)))
colnames(a) = c("info", 1:20)
colnames(b) = c("info", 1:20)
colnames(c) = c("info", 1:20)

#identify all dataframes for looping rollmean
dflist = as.list(ls()[sapply(mget(ls(), .GlobalEnv), is.data.frame)]

#for loop to create rolling average and save as new dataframe
for (j in 1:length(dflist)){
  list = as.list(ls()[sapply(mget(ls(), .GlobalEnv), is.data.frame)])
  new.names = as.character(unique(list))
  smoothed = as.data.frame(
     apply(
        X = names(list), MARGIN = 1, FUN = rollmean, k = 3, align = 'right'))
  assign(new.names[i], smoothed)
}

我也尝试了嵌套的套用方法,但是无法调用类似于此处问题的rollmean / rollapply函数所以我回到for循环,但是如果有人可以使用嵌套的套用来完成这项工作,那我就失望了!

图片是理想的输出:顶部是带有彩色框的单输入数据帧,该框显示所有列的滚动平均值,并在每一列上进行迭代;底部是理想的输出,其颜色反映了上面每个彩色窗口的输出位置顶部是带有彩色框的单个输入数据框,该框显示所有列的滚动平均值,并在每一列上进行迭代; 底部是理想的输出,其颜色反映了上面每个彩色窗口的输出位置

G.格洛腾迪克

以下dfnamesenv全局环境中的数据框的名称-我们已为其命名env,以防您以后需要更改它们的位置。请注意,它ls具有一个pattern=参数,并且如果数据帧名称具有不同的模式,则dfnames <- ls(pattern=whatever)可以在适当的正则表达式中使用它来代替。

现在make_newrollapplyr使用新的均值函数定义哪些调用mean3如果输入向量的长度小于3,则该函数将返回其输入的最后一个值,否则返回均值。然后循环使用过的名字rollappyrFUN=mean3partial=TRUE

library(zoo)

env <- .GlobalEnv
dfnames <- Filter(function(x) is.data.frame(get(x, env)), ls(env))

# make_new - first version
mean3 <- function(x, k = 3) if (length(x) < k) tail(x, 1) else mean(x)
make_new <- function(df) replace(df, -1, rollapplyr(df[-1], 3, mean3, partial = TRUE))

for(nm in dfnames) env[[paste(nm, "new", sep = "_")]] <- make_new(get(nm, env))

替代版本的make_new

上面显示的make_new的第一个版本的替代方法是以下第二个版本。在第二个版本,而不是限定mean3,我们使用只是简单mean但指定一个矢量宽度的wrollapplyr使得w等于C(1,1,3,3,...,3)。因此,前两个输入分量仅取最后一个元素的平均值,其余三个取最后三个元素的平均值。请注意,现在我们已经明确指定宽度,我们不再需要指定partial=

# make_new -- second version
make_new <- function(df) {
  w <- replace(rep(3, nrow(df)), 1:2, 1)
  replace(df, -1, rollapplyr(df[-1], w, mean))
}

注意

通常,在编写R并处理一组对象时,会将对象存储在列表中,而不是使它们在全局环境中松散。我们可以这样创建一个列表L,然后使用它lapply来创建L2包含新版本的第二个列表两种版本make_new都可以在这里使用。

L <- mget(dfnames, env)
L2 <- lapply(L, make_new)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章