如何修改多个数据框而不列出它们然后使用 lapply?
Posted
技术标签:
【中文标题】如何修改多个数据框而不列出它们然后使用 lapply?【英文标题】:How to modify multiple data frames without making a list of them and then using lapply? 【发布时间】:2018-02-16 05:45:29 【问题描述】:我有 20 个数据框,我想在每个数据框中以相同的方式格式化同一列。当然,我可以创建一个 list
的 dfs,然后使用 lapply
。相反,我的目标是修改 dfs,以便最终我不必将它们作为列表的元素访问,而是作为 dfs 访问。这是一个例子:
df1 <- data.frame(col1 = rnorm(5), col2 = rnorm(5))
df2 <- data.frame(col1 = rnorm(5), col2 = rnorm(5))
现在,假设我想给df1
和df2
中col1
的每个值加1。当然可以了
df_list <- lapply(list(df1, df2), function(df)
df$col1 <- df$col1 + 1
return(df)
)
但现在df1
返回原始 df 而不是修改后的。怎么做?
【问题讨论】:
如果您需要更新df1
,请在设置df_list
的名称后使用list2env(df_list, envir = .GlobalEnv)
即names(df_list) <- c("df1", "df2")
如果您不需要创建list
,则使用@ 987654335@ 循环与assign
为什么将这些作为单独的变量如此重要?为什么一开始没有在列表中创建它们?迭代环境中的对象需要get/assign which isn't ideal。如果您将相关项目保留在列表中,一切都会正常工作。
通过将 dfs 分开,我可以使用 RStudio 的数据查看器。最重要的是,显式子集(例如df$col1
)比子集复杂列表更方便。
【参考方案1】:
您可以通过这样的循环来避免该函数(及其临时环境):
df1 <- data.frame(col1 = 1:5, col2 = rnorm(5))
df2 <- data.frame(col1 = rep(0, 5), col2 = rnorm(5))
df1 # before
for (d in c("df1", "df2"))
eval(parse(text = paste(d, "[['col1']] <- ", d, "[['col1']] + 1")))
df1 # after
选项 2:
df1 <- data.frame(col1 = 1:5, col2 = rnorm(5))
df2 <- data.frame(col1 = rep(0, 5), col2 = rnorm(5))
df1 # before
df2 # before
eval(parse(text = unlist(lapply(c("df1", "df2"), function(x)
expr.dummy <- quote(df$col1 <- df$col1 +1) # df will be replaced by df1, df2
gsub("df", x, deparse(expr.dummy))
))))
df1 # after
df2 # after
【讨论】:
【参考方案2】:您可以在这个问题中使用来自@g-grothendieck 的技巧:
http://***.com/questions/1826519/how-to-assign-from-a-function-which-returns-more-than-one-value
然后这样做:
list[df1, df2] <- lapply(list(df1, df2), function(df)
df$col1 <- df$col1 + 1
return(df)
)
黑客攻击
list <- structure(NA,class="result")
"[<-.result" <- function(x,...,value)
args <- as.list(match.call())
args <- args[-c(1:2,length(args))]
length(value) <- length(args)
for(i in seq(along=args))
a <- args[[i]]
if(!missing(a)) eval.parent(substitute(a <- v,list(a=a,v=value[[i]])))
x
完整代码和结果
df1 <- data.frame(col1 = rnorm(5), col2 = rnorm(5))
# col1 col2
# 1 -0.5451934 0.5043287
# 2 -1.4047701 -0.1184588
# 3 0.1745109 0.8279085
# 4 -0.5066673 -0.3269411
# 5 0.4838625 -0.3895784
df2 <- data.frame(col1 = rnorm(5), col2 = rnorm(5))
# col1 col2
# 1 0.4168078 -0.44654445
# 2 -1.9991098 -0.06179699
# 3 -1.0625996 1.21098946
# 4 0.4977718 0.45834008
# 5 -1.6181048 0.97917877
list[df1, df2] <- lapply(list(df1, df2), function(df)
df$col1 <- df$col1 + 1
return(df)
)
# > df1
# col1 col2
# 1 0.4548066 0.5043287
# 2 -0.4047701 -0.1184588
# 3 1.1745109 0.8279085
# 4 0.4933327 -0.3269411
# 5 1.4838625 -0.3895784
# > df2
# col1 col2
# 1 1.41680778 -0.44654445
# 2 -0.99910976 -0.06179699
# 3 -0.06259959 1.21098946
# 4 1.49777179 0.45834008
# 5 -0.61810483 0.97917877
【讨论】:
【参考方案3】:基于 OP 代码的一个选项是在命名 list
元素后使用 list2env
names(df_list) <- paste0("df", 1:2)
list2env(df_list, envir = .GlobalEnv)
如果我们需要避免创建list
(建议有一个list
的数据集,而不是在全局环境中创建单个对象),那么使用assign
和for
循环
for(obj in paste0('df', 1:2))
assign(obj, `[<-`(get(obj), 'col1', value = get(obj)[['col1']] +1))
【讨论】:
以上是关于如何修改多个数据框而不列出它们然后使用 lapply?的主要内容,如果未能解决你的问题,请参考以下文章
在闪亮的 server.R 中更新数据框而不重新启动应用程序
单击保存按钮后如何在用户窗体中添加依赖于另一个组合框的excel vba组合框而不影响清除数据功能
如何在 MS ACCESS 中打开定时消息框而不创建其他窗口