2012-03-04 204 views
3

我的Excel数据集中每周都有一个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_excused”到最后的数据帧中的单个“缺席”一栏,所以我试图让我的解决方案,让我执行转换到新的栏目,像这样(再次,这是不对的):

Cleaned$Absences.i <- all.sheets[[i]][,c("Absences")] + all.sheets[[i]][,c("Absences_excused")] 
+0

我想你应该清楚,我们是否可以期待的所有片材具有相同的价值观和顺序名== ID ,性别,生日。如果不是,那么'merge'显然是你想要的功能,如果是这样的话,'cbind'就足够了。 – 2012-03-04 02:21:17

+0

所有工作表都具有相同的值并订购ID,性别,DOB和其他常量列。他们没有相同的缺勤值,缺勤报告等值。 – Andrew 2012-03-04 02:23:53

+0

我没有看到任何“原谅”的列。 – 2012-03-04 02:35:10

回答

3

@Dinin我觉得海报的问题比这个例子让我们相信要复杂一点。我认为海报希望进行多合并,如“第1周,第2周第2周等”所示。我的方法有点不同。额外的障碍可以在合并之前使用lapply进行转换。这是我使用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 

一个第二个方法(重命名数据帧列之后)是使用减少:(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')) 

两者我不知道哪一个是,虽然速度更快。

编辑:在Windows 7计算机上运行1000次迭代的减少是速度快:

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 
+0

这是完美的。谢谢! – Andrew 2012-03-04 06:58:49

7

合并策略是:

> Week_1_sheet <- read.table(text="ID Gender DOB Absences Lates 
+ 1  M   1997 5   14 
+ 2  F   1998 4   3", header=TRUE) 
> Week_2_sheet <- read.table(text="ID Gender DOB Absences Lates 
+ 1  M   1997 2   10 
+ 2  F   1998 8   2", header=TRUE) 
> merge(Week_1_sheet, Week_2_sheet, 1:3) 
    ID Gender DOB Absences.x Lates.x Absences.y Lates.y 
1 1  M 1997   5  14   2  10 
2 2  F 1998   4  3   8  2 

您可以names(sheet) <- sub("x", 1, sheet)再次y的重命名列, - > 2.我认为cbi nd策略是可以的,但合并可能更好学习。

@TylerRinker提出了关于'by'参数的可接受参数的问题。帮助页面中的相关参数是:“列可以通过名称,编号或逻辑向量指定:名称”row.names“或编号0指定行名称。”

+2

我不知道你可以在合并中使用列号作为参数。 +1 – 2012-03-04 05:58:27

相关问题