2011-11-04 65 views
3

我想重塑一個數據幀重組數據幀:[R重塑,由大塊

目前,它看起來像這樣:

ID | Gender |A1 | A2 | A3 | B1 | B2 | B3 
ID_1 | m  | 3 | 3 | 3 | 2 | 3 | 2 
ID_2 | f  | 1 | 1 | 1 | 4 | 4 | 4 

我想有這樣的:

ID | Gender | A1 | A2 | A3 
ID_1 | m  | 3 | 3 | 3 <- this would be columns A1 - A3 for ID 1 
ID_1 | m  | 2 | 2 | 2 <- this would be columns B1 - B3 for ID 1 
ID_2 | f  | 1 | 1 | 1 <- this would be columns A1 - A3 for ID 2 
ID_2 | f  | 4 | 4 | 4 <- this would be columns B1 - B3 for ID 2 

( A1和B1/A2和B2是相同的變量(關於內容),例如:A1和B1將是測試1結果的變量,A2和B2都包含測試2的結果。因此,在爲了評估使用它我需要一列中的Test1的結果和另一列中的所有Test2的結果。 我試圖用「融化」來解決這個問題,但它只能將數據框一個接一個地融化,而不是大塊。 (因爲我需要保持前2列的方式,只重新排列最後4列,但作爲三個塊) 任何其他想法?謝謝!

+0

告訴'melt'的前兩列分別爲id的變量,即'id.vars = ...' – Andrie

+0

第一部分工作,保留第一列是沒有問題的,但是我不知道如何告訴R它應該重新排列所有Test1(A1,B1)/ Test2(A2,B2)等等。因此,我最終得到了三個而不是六個列(例如兩個)... – Elisa

+0

@Elisa,這看起來像是你幾個小時前創建的問題的重複。如果是,請關閉另一個。 – Ramnath

回答

5

一個襯墊使用reshape從基地R.

reshape(dat, varying = 3:8, idvar = 1:2, direction = 'long', drop=FALSE, 
    timevar = 'Test') 

      ID Gender Test Test1 Test2 Test3 
ID_1.m.A ID_1  m A A1 A2 A3 
ID_2.f.A ID_2  f A A1 A2 A3 
ID_1.m.B ID_1  m B B1 B2 B3 
ID_2.f.B ID_2  f B B1 B2 B3 
+0

+1 - 很難打敗這個解決方案。任何人都知道如何(在一行內)放棄那些醜陋的'row.names'? –

+0

你可以通過添加一個參數'new.row.names = 1:4'來刪除'row.name'。如果你不想硬編碼4,你可以很容易地找出如何基於數據計算它。 – Ramnath

+0

這個計算是我無法/無法弄清楚的。很好 - 即使是雙線,這非常好。 –

2

正如@Andrie所說,第一步就是用給定的列(ID和性別)來融合數據。正如你所說,你的問題是確定哪些列然後「走到一起」。這裏有一種方法,最初將這些信息編碼成列名,然後從那裏拉出來。

首先是一些虛擬數據

dat <- data.frame(ID=c("ID_1", "ID_2"), Gender=c("m","f"), 
    Test1.A = "A1", Test2.A = "A2", Test3.A = "A3", 
    Test1.B = "B1", Test2.B = "B2", Test3.B = "B3", stringsAsFactors=FALSE) 

請注意,我已經與系統指示哪些測試和基時,一部分的名字命名的列。

> dat 
    ID Gender Test1.A Test2.A Test3.A Test1.B Test2.B Test3.B 
1 ID_1  m  A1  A2  A3  B1  B2  B3 
2 ID_2  f  A1  A2  A3  B1  B2  B3 

使用reshape2

library("reshape2") 

熔體中的數據,再取variable柱,其具有的兩個信息在它(測試和組),和分割信息的這兩個比特到兩個單獨的列。

dat.m <- melt(dat, id.vars=c("ID", "Gender")) 
dat.m <- cbind(dat.m, colsplit(dat.m$variable, "\\.", names=c("Test", "Group"))) 

現在很容易投射,因爲測試和組是分開的。

dcast(dat.m, ID+Gender+Group~Test) 

其中給出

> dcast(dat.m, ID+Gender+Group~Test) 
    ID Gender Group Test1 Test2 Test3 
1 ID_1  m  A A1 A2 A3 
2 ID_1  m  B B1 B2 B3 
3 ID_2  f  A A1 A2 A3 
4 ID_2  f  B B1 B2 B3 
0

如何:

> dat <- data.frame(id=c("id1","id2"),gender=c("m","f"),a.1=1:2,a.2=1:2,a.3=1:2,b.1=3:4,b.2=3:4,b.3=3:4) 
> dat1 <- dat[,-(3:5)] 
> dat2 <- dat[,-(6:8)] 
> names(dat1)[3:5] <- c("v1","v2","v3") 
> names(dat2)[3:5] <- c("v1","v2","v3") 
> 
> dat1$test <- "b" 
> dat2$test <- "a" 
> result <- rbind(dat1,dat2) 
> dat 
    id gender a.1 a.2 a.3 b.1 b.2 b.3 
1 id1  m 1 1 1 3 3 3 
2 id2  f 2 2 2 4 4 4 
> result 
    id gender v1 v2 v3 test 
1 id1  m 3 3 3 b 
2 id2  f 4 4 4 b 
3 id1  m 1 1 1 a 
4 id2  f 2 2 2 a 
1

我喜歡Brian的回答更好,但這裏有一個方法與基本包做。雖然在我看來很醜。

您的數據框:

DF 
     id sex v1 v2 v3 v4 v5 v6 
    1 ID_1 male A1 A2 A3 B1 B2 B3 
    2 ID_2 female A1 A2 A3 B1 B2 B3 

代碼

DFa<-subset(DF, select=c(1:5)) 
DFb<-subset(DF, select=c(1:2, 6:8)) 
colnames(DFb)<-colnames(DFa) 
DF<-as.data.frame(rbind(DFa,DFb)) 
rownames(DF)<-1:nrow(DF) 
DF[order(DF$id),] 
+0

約翰我不同意。我看到輸出與OP的預期結果相同。只有4行不是6,所以我不明白你的批評。 –

+0

我的答覆和其他答案之間的唯一區別是我不給A和B單獨列,因爲它是答案中固有的(這可能是一個問題,但如果A1,A2,B1 ...實際上是數字)我對這些行進行了重新排序以匹配所需的結果。這是一個簡單的情況,分裂列和restacking。 –

+0

當我第一次複製和粘貼你的代碼時,它出於某種原因做了6行。現在它不。抱歉。 – John