我浏览了各个带有类似问题(有些链接)的“溢出”页面,但没有发现任何似乎可以帮助完成此复杂任务的内容。
我的工作区中有一系列数据框,我想在所有这些框上循环使用相同的功能(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循环,但是如果有人可以使用嵌套的套用来完成这项工作,那我就失望了!
图片是理想的输出:顶部是带有彩色框的单输入数据帧,该框显示所有列的滚动平均值,并在每一列上进行迭代;底部是理想的输出,其颜色反映了上面每个彩色窗口的输出位置
以下dfnames
是env
全局环境中的数据框的名称-我们已为其命名env
,以防您以后需要更改它们的位置。请注意,它ls
具有一个pattern=
参数,并且如果数据帧名称具有不同的模式,则dfnames <- ls(pattern=whatever)
可以在适当的正则表达式中使用它来代替。
现在make_new
,rollapplyr
使用新的均值函数定义哪些调用,mean3
如果输入向量的长度小于3,则该函数将返回其输入的最后一个值,否则返回均值。然后循环使用过的名字rollappyr
与FUN=mean3
和partial=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的第一个版本的替代方法是以下第二个版本。在第二个版本,而不是限定mean3
,我们使用只是简单mean
但指定一个矢量宽度的w
在rollapplyr
使得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] 删除。
我来说两句