2013-10-17 39 views
1

我有一個數據幀,看起來像這樣:使用merged.stack從大表創建一個長表(或重塑)

ID rd_test_2011 rd_score_2011 mt_test_2011 mt_score_2011 rd_test_2012 rd_score_2012 mt_test_2012 mt_score_2012 
1 A   80   XX   100   NA   NA   BB   45 
2 XX   90   NA   NA   AA   80   XX   80 

我想編寫一個腳本,將用於標識,唐」 t在yy_test_20xx列中包含NA,創建一個新的數據框,其中包含從列標題獲取的主題,測試名稱,測試分數和從列標題獲取的年份。所以,在這個例子中,ID 1會有三個條目。預計輸出應該是這樣的:

ID Subject Test  Score  Year 
1 rd   A   80   2011 
1 mt   XX   100   2012 
1 mt   BB   45   2012 
2 rd   XX   90   2011 
2 rd   AA   80   2012 
2 mt   XX   80   2012 

我已經試過merged.stack這在這個意義上,我得到的輸出是在馬路上是正確的作品既重塑和各種形式的,但我不能瞭解投入不夠好到那裏一路:與重塑

library(splitstackshape) 
merged.stack(x, id.vars='id', var.stubs=c("rd_test","mt_test"), sep="_") 

我有更多的成功(變得更近):

y<- reshape(x, idvar="id", ids=1:nrow(x), times=grep("test", names(x), value=TRUE), 
     timevar="year", varying=list(grep("test", names(x), value=TRUE), grep("score", 
     names(x), value=TRUE)), direction="long", v.names=c("test", "score"), 
     new.row.names=NULL) 
+0

1. [你嘗試過什麼(http://mattgemmell.com/2008/12/08/what-you-you-tried /)到目前爲止? 2.預期的產出會很有用。 – zero323

+0

您正在尋找'reshape' –

+0

@SeñorO我無法識別重塑的正確參數是什麼,因爲我正在使用的數據框有大約100列和大約150000行,我只想重塑一些專欄。 – n8sty

回答

2

這將讓您的數據轉換成合適的格式:

df.long = reshape(df, idvar="ID", ids=1:nrow(df), times=grep("Test", names(df), value=TRUE), 
timevar="Year", varying=list(grep("Test", names(df), value=TRUE), 
grep("Score", names(df), value=TRUE)), direction="long", v.names=c("Test", "Score"), 
new.row.names=NULL) 

然後省略NA

df.long = df.long[!is.na(df.long$Test),] 

然後分裂Year刪除Test_

df.long$Year = sapply(strsplit(df.long$Year, "_"), `[`, 2) 

和訂購ID

df.long[order(df.long$ID),] 

    ID Year Test Score 
1 1 2011 A 80 
5 1 2012 XX 100 
2 2 2011 XX 90 
9 2 2013 AA 80 
6 3 2012 A 10 
3 4 2011 A 50 
7 4 2012 XX 60 
10 4 2013 AA 99 
4 5 2011 C 50 
8 5 2012 A 75 
+1

我建議你用這個代替時間:'times = gsub('。* _','',grep(「Test」,names(dat),value = TRUE))',你會得到比我更通用的解決方案,你省略了分裂的一年。當然是+1! – agstudy

+0

是的,我在印象中'時代'正在做不同的列匹配。 –

2

使用reshape

dat.long <- reshape(dat, direction="long", varying=list(c(2, 4,6), c(3, 5,7)), 
         times=2011:2013,timevar='Year', 
         sep="_", v.names=c("Test", "Score")) 


dat.long[complete.cases(dat.long),] 

     ID Year Test Score id 
1.2011 1 2011 A 80 1 
2.2011 2 2011 XX 90 2 
4.2011 4 2011 A 50 4 
5.2011 5 2011 C 50 5 
1.2012 1 2012 XX 100 1 
3.2012 3 2012 A 10 3 
4.2012 4 2012 XX 60 4 
5.2012 5 2012 A 75 5 
2.2013 2 2013 AA 80 2 
4.2013 4 2013 AA 99 4 
+0

+1。我一直在努力以簡單的格式重塑形狀。 –

1

考慮到您的更新,我已經完全重寫了這個答案。如果您想查看舊版本,請查看歷史記錄。

主要問題是您的數據在某種程度上是「雙倍寬」。因此,您可以通過兩次重新「長」方向來解決問題。或者,使用melt*cast以非常長的格式融化數據並將其轉換爲半寬格式。

但是,我仍然會建議「splitstackshape」(而不只是因爲我寫了它)。它可以很好地處理這個問題,但它需要你重新排列你的數據的names。名稱中將導致新列名稱的部分應該排在第一位。在你的例子中,這意味着「測試」和「分數」應該是變量名的第一部分。

爲此,我們可以使用一些gsub重新排列現有名稱。

library(splitstackshape) 
setnames(mydf, gsub("(rd|mt)_(score|test)_(.*)", "\\2_\\1_\\3", names(mydf))) 
names(mydf) 
# [1] "ID"   "test_rd_2011" "score_rd_2011" "test_mt_2011" 
# [5] "score_mt_2011" "test_rd_2012" "score_rd_2012" "test_mt_2012" 
# [9] "score_mt_2012" 
out <- merged.stack(mydf, "ID", var.stubs=c("test", "score"), sep="_") 
setnames(out, c(".time_1", ".time_2"), c("Subject", "Year")) 
out[complete.cases(out), ] 
# ID Subject Year test score 
# 1: 1  mt 2011 XX 100 
# 2: 1  mt 2012 BB 45 
# 3: 1  rd 2011 A 80 
# 4: 2  mt 2012 XX 80 
# 5: 2  rd 2011 XX 90 
# 6: 2  rd 2012 AA 80 

對於其他人的利益,在這個答案 「是myDF」 被定義爲:

mydf <- structure(list(ID = 1:2, rd_test_2011 = c("A", "XX"), 
    rd_score_2011 = c(80L, 90L), mt_test_2011 = c("XX", NA), 
    mt_score_2011 = c(100L, NA), rd_test_2012 = c(NA, "AA"), 
    rd_score_2012 = c(NA, 80L), mt_test_2012 = c("BB", "XX"), 
    mt_score_2012 = c(45L, 80L)), 
    .Names = c("ID", "rd_test_2011", "rd_score_2011", "mt_test_2011", 
    "mt_score_2011", "rd_test_2012", "rd_score_2012", "mt_test_2012", 
    "mt_score_2012"), class = "data.frame", row.names = c(NA, -2L))