我的数据集中有一个 Excel 文件,每周都有一张工作表。每张纸都有相同的行数,并且每张纸上的每一行都是相同的(时间段除外……第 1 表代表第 1 周,第 2 表代表第 2 周,以此类推)。我正在尝试将所有 Excel 工作表作为 R 中的一个数据框导入。

例如,我的数据基本上是这样结构的(还有几个列和工作表):

Week 1 sheet
ID    Gender    DOB    Absences    Lates    Absences_excused
1     M         1997   5           14       5
2     F         1998   4           3        2

Week 2 sheet
ID    Gender    DOB    Absences    Lates    Absences_excused
1     M         1997   2           10       3
2     F         1998   8           2        9

我正在尝试构建一个脚本,该脚本将采用 x 张数并将它们组合成一个数据框,如下所示:
Combined (ideal)
ID    Gender    DOB    Absences.1    Lates.1    Absences.2    Lates.2
1     M         1997   5             14         2             10
2     F         1998   4             3          8             2

我正在使用 gdata 导入 Excel 文件。

我尝试创建一个循环(通常对 R 不利,我知道......)它将遍历 Excel 文件中的所有工作表并将每个工作表作为数据框添加到列表中:
library(gdata)

number_sheets <- 3
all.sheets <- vector(mode="list", length=number_sheets)

for (i in 1:number_sheets) {
  all.sheets[[i]] <- read.xls("/path/to/file.xlsx", sheet=i)
}

这为我提供了一个不错的列表 all.sheets ,我可以访问它,但我不确定从数据框列表中的特定列创建新数据框的最佳方法。

我已经尝试了下面的代码,它通过循环遍历数据框列表来创建一个全新的数据框。在第一个数据框中,它保存所有工作表中一致的列,然后添加特定于周的列。
Cleaned <- data.frame()
number_sheets <- 3

for (i in 1:number_sheets) {
  if (i == 1) {
    Cleaned <- all.sheets[[i]][,c("ID", "Gender", "DOB")]
  }
  Cleaned$Absences.i <- all.sheets[[i]][,c("Absences")]  # wrong... obviously doesn't work... but essentially what I want
  # Other week-specific columns go here... somehow...
}

但是,此代码不起作用,因为 Cleaned$Absences.i 显然不是您在数据框中创建动态列的方式。

组合一组数据框并为我要跟踪的每个变量创建新列的最佳方法是什么?

额外的障碍:我还尝试将两列“Absences”和“Absences_excused”合并到最终数据框中的单个“Absences”列中,因此我试图让我的解决方案让我对新列执行转换,像这样(同样,这是不对的):
Cleaned$Absences.i <- all.sheets[[i]][,c("Absences")] + all.sheets[[i]][,c("Absences_excused")]

最佳答案

@DWin 我认为海报的问题比示例中让我们相信的要复杂一些。我认为海报想要多合并,如“第 1 周、第 2 周第 2 周等”所示。我的方法有点不同。在合并之前可以使用 lapply with transform 处理额外的障碍。这是我使用 3 个数据框而不是 2 个进行合并的解决方案。

#First read in three data frames
Week_1_sheet <- read.table(text="ID Gender  DOB Absences Unexcused_Absences Lates
1  1      M 1997        5                  1    14
2  2      F 1998        4                  2     3", header=TRUE)

Week_2_sheet <- read.table(text="ID Gender  DOB Absences Unexcused_Absences Lates
1  1      M 1997        2                  1    10
2  2      F 1998        8                  2     2
3  3      M 1998        8                  2     2", header=TRUE)

Week_3_sheet <- read.table(text="ID Gender  DOB Absences Unexcused_Absences Lates
1  1      M 1997        2                  1    10
2  2      F 1998        8                  2     2", header=TRUE)

#Put them into a list structure
WEEKlist <- list(Week_1_sheet , Week_2_sheet , Week_3_sheet)

#Transform to add the absences and unexcused absences and drop unexcused
lapply(seq_along(WEEKlist), function(x) {
    WEEKlist[[x]] <<- transform(WEEKlist[[x]], Absences=sum(Absences,
        Unexcused_Absences))[, -5]
    }
)

#Rename each data frame in the list with `<<-` that acts on environments
lapply(seq_along(WEEKlist), function(x) {
    y <- names(WEEKlist[[x]])
    names(WEEKlist[[x]]) <<- c(y[1:3], paste(y[4:length(y)], ".", x, sep=""))
    }
)

#loop through and merge by the common columns
DF <- WEEKlist[[1]][, 1:3]
for (.df in WEEKlist) {
     DF <-merge(DF, .df, by=c('ID', 'Gender', 'DOB'), all=TRUE, suffixes=c("", ""))
}

DF

第二种方法(重命名数据框列之后)是使用 Reduce:
取自 (LINK)
merge.all <- function(frames, by) {
    return (Reduce(function(x, y) {merge(x, y, by = by, all = TRUE)}, frames))
}

merge.all(frames=WEEKlist, by=c('ID', 'Gender', 'DOB'))

我不确定哪个更快。

编辑:在运行 1000 次迭代的 Windows 7 机器上,Reduce 更快:
    test replications elapsed relative user.self sys.self
1   LOOP         1000   10.12  1.62701      7.89        0
2 REDUCE         1000    6.22  1.00000      5.34        0

关于r - 组合一系列数据框并为每个数据框创建新列,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/9551555/

10-09 06:25
查看更多