如何在 R 中的 reshape 包中循环 dcast 函数
How to loop dcast function in reshape package in R
作为一个相对较新的 R 用户,我在使用任何循环函数时遇到了麻烦。我看过很多教程,但其中的示例通常非常基础,因此易于执行。但是,我需要创建稍微复杂一些的循环,并且在弄清楚如何这样做时遇到了很多麻烦。这里和其他论坛上有一些相关的循环问题,但 none 完全符合我的需要,尽管我已尝试针对我当前的问题调整其他答案,但我仍然 运行 出错。
我有 2000 个 .csv 文件,其中的数据以长格式数据列出(简化示例):
solution1
> sol1 sol2 Istat
> s1 s2 0.435
> s1 s3 0.456
> s1 s4 0.845
> s1 s5 0.234
它基本上是对我拥有的 2000 个单独解决方案的成对比较的总结,解决方案之间的相似性总结在一个 'Istat' 值中。
我正在尝试将这 2000 个 .csv 文件中的每一个都转换为宽格式 table(使用 R 中的重塑包),因此它们看起来像(以下示例):
s1 s2 s3 s4 s5
s1 NA 0.435 0.456 0.845 0.234
我知道如何使用一个 .csv 文件只执行一次:
stat.cast <- dcast(solution1, sol2 ~ sol1, value.var="Istat")
但我似乎无法将其放入 for
循环函数中,甚至无法使用 lapply
,这似乎也是一个可能的解决方案。
我用 for
函数得到的最接近值:
# Get files from directory
loopout = "/Users/jc219806/Documents/Chapter 1/ANALYSES/R work/Istat/last_LoopOut/"
# List of file names inside folder
solutions <- list.files(loopout)
# Read all 2000 files inside
all.data <- lapply(solutions, read.csv, header=TRUE)
# Loop for performing reshape cast function to each listed dataframe
for (i in 1:length(all.data))
{
all.cast <- dcast(all.data, sol2 ~ sol1, value.var="Istat")
}
但它一直给我错误,它无法从输入中识别 "Istat" 值 - 即使它存在于我拥有的数据帧列表中(代码中的 "solutions" 对象以上)。
并使用 lapply
函数:
lapply(solutions, dcast(all.data, sol2 ~ sol1, value.var="Istat"))
我遇到了同样类型的错误:
Error: value.var (Istat) not found in input
我不明白为什么,因为它列在数据帧列表中,作为每个 2000 个数据帧中的变量之一。似乎我没有让它正确地遍历我的每个 2000 .csv 文件,但我不知道如何解决这个问题。我还想知道是否也可以编写代码,以便循环根据列名将所有 2000 个输出绑定在一起?它正在疯狂循环。
我希望这个问题没有我想象的那么复杂。任何帮助(连同一些详细的解释)或有用的指导将不胜感激。谢谢
"all.data" 是数据帧列表。要遍历列表,您可以使用 lapply
和匿名函数调用(只是为了清楚起见)并在其上应用 dcast
。
library(reshape2)
lapply(all.data, function(x) dcast(x, sol1 ~ sol2, value.var="Istat"))
或者不执行单独的 dcast
,列表可以 rbind
到数据框,每个列表元素都有一个分组变量,然后执行 dcast
或 spread
来自 library(tidyr)
library(dplyr)
library(tidyr)
unnest(all.data, group) %>%
spread(sol2, Istat)
或使用data.table
library(data.table)
dcast(rbindlist(Map(cbind, all.data, group=seq_along(all.data))),
group + sol1 ~sol2, value.var='Istat')
数据
all.data <- structure(list(solution1 = structure(list(sol1 = c("s1",
"s1",
"s1", "s1"), sol2 = c("s2", "s3", "s4", "s5"), Istat = c(0.435,
0.456, 0.845, 0.234)), .Names = c("sol1", "sol2", "Istat"),
class = "data.frame", row.names = c(NA,
-4L)), solution2 = structure(list(sol1 = c("s1", "s1", "s1",
"s1"), sol2 = c("s2", "s3", "s4", "s5"), Istat = c(0.42, 0.536,
0.945, 0.324)), .Names = c("sol1", "sol2", "Istat"),
class = "data.frame", row.names = c(NA,
-4L))), .Names = c("solution1", "solution2"))
您写道:
for (i in 1:length(all.data))
{
all.cast <- dcast(all.data, sol2 ~ sol1, value.var="Istat")
}
你应该写的:
all.cast <- list()
for (i in 1:length(all.data)) {
all.cast[[i]] <- dcast(all.data[[i]], sol2 ~ sol1, value.var = "Istat")
}
但更 "R-esque" 的解决方案是:
all.cast <- lapply(all.data, dcast, sol2 ~ sol1, value.var = "Istat")
希望这能让你明白你做错了什么。
我会 melt
您的 "all.data" 列表,然后 dcast
将它变成宽格式。类似于:
## Sample data
set1 <- set2 <- data.frame(sol1 = c("s1", "s1", "s1", "s1"),
sol2 = c("s2", "s3", "s4", "s5"),
Istat = c(0.435, 0.456, 0.845, 0.234))
set2$Istat <- set2$Istat + 1 ## Just to see some different data
all.data <- mget(ls(pattern = "set\d+")) ## use your actual object
## The reshaping
library(reshape2)
dcast(melt(all.data, id.vars = c("sol1", "sol2")),
L1 + sol1 ~ sol2, value.var = "value")
# L1 sol1 s2 s3 s4 s5
# 1 set1 s1 0.435 0.456 0.845 0.234
# 2 set2 s1 1.435 1.456 1.845 1.234
如果您的 "all.data" 对象有名称,"L1" 将反映这些名称,这在长 运行.
中非常方便
作为一个相对较新的 R 用户,我在使用任何循环函数时遇到了麻烦。我看过很多教程,但其中的示例通常非常基础,因此易于执行。但是,我需要创建稍微复杂一些的循环,并且在弄清楚如何这样做时遇到了很多麻烦。这里和其他论坛上有一些相关的循环问题,但 none 完全符合我的需要,尽管我已尝试针对我当前的问题调整其他答案,但我仍然 运行 出错。
我有 2000 个 .csv 文件,其中的数据以长格式数据列出(简化示例):
solution1
> sol1 sol2 Istat
> s1 s2 0.435
> s1 s3 0.456
> s1 s4 0.845
> s1 s5 0.234
它基本上是对我拥有的 2000 个单独解决方案的成对比较的总结,解决方案之间的相似性总结在一个 'Istat' 值中。
我正在尝试将这 2000 个 .csv 文件中的每一个都转换为宽格式 table(使用 R 中的重塑包),因此它们看起来像(以下示例):
s1 s2 s3 s4 s5
s1 NA 0.435 0.456 0.845 0.234
我知道如何使用一个 .csv 文件只执行一次:
stat.cast <- dcast(solution1, sol2 ~ sol1, value.var="Istat")
但我似乎无法将其放入 for
循环函数中,甚至无法使用 lapply
,这似乎也是一个可能的解决方案。
我用 for
函数得到的最接近值:
# Get files from directory
loopout = "/Users/jc219806/Documents/Chapter 1/ANALYSES/R work/Istat/last_LoopOut/"
# List of file names inside folder
solutions <- list.files(loopout)
# Read all 2000 files inside
all.data <- lapply(solutions, read.csv, header=TRUE)
# Loop for performing reshape cast function to each listed dataframe
for (i in 1:length(all.data))
{
all.cast <- dcast(all.data, sol2 ~ sol1, value.var="Istat")
}
但它一直给我错误,它无法从输入中识别 "Istat" 值 - 即使它存在于我拥有的数据帧列表中(代码中的 "solutions" 对象以上)。
并使用 lapply
函数:
lapply(solutions, dcast(all.data, sol2 ~ sol1, value.var="Istat"))
我遇到了同样类型的错误:
Error: value.var (Istat) not found in input
我不明白为什么,因为它列在数据帧列表中,作为每个 2000 个数据帧中的变量之一。似乎我没有让它正确地遍历我的每个 2000 .csv 文件,但我不知道如何解决这个问题。我还想知道是否也可以编写代码,以便循环根据列名将所有 2000 个输出绑定在一起?它正在疯狂循环。
我希望这个问题没有我想象的那么复杂。任何帮助(连同一些详细的解释)或有用的指导将不胜感激。谢谢
"all.data" 是数据帧列表。要遍历列表,您可以使用 lapply
和匿名函数调用(只是为了清楚起见)并在其上应用 dcast
。
library(reshape2)
lapply(all.data, function(x) dcast(x, sol1 ~ sol2, value.var="Istat"))
或者不执行单独的 dcast
,列表可以 rbind
到数据框,每个列表元素都有一个分组变量,然后执行 dcast
或 spread
来自 library(tidyr)
library(dplyr)
library(tidyr)
unnest(all.data, group) %>%
spread(sol2, Istat)
或使用data.table
library(data.table)
dcast(rbindlist(Map(cbind, all.data, group=seq_along(all.data))),
group + sol1 ~sol2, value.var='Istat')
数据
all.data <- structure(list(solution1 = structure(list(sol1 = c("s1",
"s1",
"s1", "s1"), sol2 = c("s2", "s3", "s4", "s5"), Istat = c(0.435,
0.456, 0.845, 0.234)), .Names = c("sol1", "sol2", "Istat"),
class = "data.frame", row.names = c(NA,
-4L)), solution2 = structure(list(sol1 = c("s1", "s1", "s1",
"s1"), sol2 = c("s2", "s3", "s4", "s5"), Istat = c(0.42, 0.536,
0.945, 0.324)), .Names = c("sol1", "sol2", "Istat"),
class = "data.frame", row.names = c(NA,
-4L))), .Names = c("solution1", "solution2"))
您写道:
for (i in 1:length(all.data))
{
all.cast <- dcast(all.data, sol2 ~ sol1, value.var="Istat")
}
你应该写的:
all.cast <- list()
for (i in 1:length(all.data)) {
all.cast[[i]] <- dcast(all.data[[i]], sol2 ~ sol1, value.var = "Istat")
}
但更 "R-esque" 的解决方案是:
all.cast <- lapply(all.data, dcast, sol2 ~ sol1, value.var = "Istat")
希望这能让你明白你做错了什么。
我会 melt
您的 "all.data" 列表,然后 dcast
将它变成宽格式。类似于:
## Sample data
set1 <- set2 <- data.frame(sol1 = c("s1", "s1", "s1", "s1"),
sol2 = c("s2", "s3", "s4", "s5"),
Istat = c(0.435, 0.456, 0.845, 0.234))
set2$Istat <- set2$Istat + 1 ## Just to see some different data
all.data <- mget(ls(pattern = "set\d+")) ## use your actual object
## The reshaping
library(reshape2)
dcast(melt(all.data, id.vars = c("sol1", "sol2")),
L1 + sol1 ~ sol2, value.var = "value")
# L1 sol1 s2 s3 s4 s5
# 1 set1 s1 0.435 0.456 0.845 0.234
# 2 set2 s1 1.435 1.456 1.845 1.234
如果您的 "all.data" 对象有名称,"L1" 将反映这些名称,这在长 运行.
中非常方便