2012-03-04 266 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

相關問題