2012-11-19 33 views
3

我有一個表,看起來像這樣:重塑表中「長」格式,以分隔列

|Condition|Session|Time| 
|  A|  1| 100| 
|  A|  1| 200| 
|  B|  2| 200| 
|  B|  2| 300| 
|  B|  2| 500| 
|  A|  3| 300| 
|  A|  4| 200| 

我想將其轉換爲以下格式:

| A| B| A| A| 
| 1| 2| 3| 4| 
| 100| 200| 300| 200| 
| 200| 300| | | 
| | 500| | | 

意義前兩行是「條件」和「會話」,其餘行代表「時間」列(可變行數)。

如何在R中實現這一點?

+0

我覺得作爲一個總體戰略,我會試圖到原來的DF重塑成一個寬一個地方開始列名是Condiion.Session,例如A.1,B.2。 A.3,A.4。我只是將colnames轉換成2行的df,然後將df轉換成df。 – frankc

+0

讀者可能會注意到,每個回答者都包含如何通過read.table或data.frame將示例錶轉換爲R可讀代碼的代碼。在'dput(mytable)'中使用'dput()'並且在問題中包含結果將會是一種有禮貌的方式來保存這一步。 :-) – MattBagg

+0

@MattBagg你是對的,這不是很禮貌 – kshahar

回答

1

我提供使用從plyrddplydcast另一個可能的解決方案從reshape2

library(reshape2) 
library(plyr) 

dat = read.table(text=gsub("\\|", " ", "|Condition|Session|Time| 
|  A|  1| 100| 
|  A|  1| 200| 
|  B|  2| 200| 
|  B|  2| 300| 
|  B|  2| 500| 
|  A|  3| 300| 
|  A|  4| 200|"), header=TRUE) 

# Add column 'Rank' for each combination of Condition by Session. 
dat = ddply(dat, .(Condition, Session), .fun=summarise, 
      Rank=rank(Time), Time=Time) 

res = dcast(dat, Condition + Session ~ Rank, value.var="Time") 

# Sort by 'Session'. 
res = res[order(res$Session), ] 

# As @Ali pointed out, you may want to leave the results as 
# an un-transposed data.frame. 
res 

# Condition Session 1 2 3 
# 1   A  1 100 200 NA 
# 4   B  2 200 300 500 
# 2   A  3 300 NA NA 
# 3   A  4 200 NA NA 

# Transposing will coerce the data.frame to a character matrix. 
t(res) 

#   1  4  2  3  
# Condition "A" "B" "A" "A" 
# Session "1" "2" "3" "4" 
# 1   "100" "200" "300" "200" 
# 2   "200" "300" NA NA 
# 3   NA "500" NA NA 
1

首先,data.frame的每一列都具有相同的類型。所以你可以把你想要的桌子放在一個轉置的形狀中。

也許你可以做如下:

foo = data.frame(Condition=c("A","A","B","B","B","A","A"), 
       Session=c(1,1,2,2,2,3,4), 
       Time = c(1,2,2,3,5,3,2)*100) 
bar = aggregate(Time~Condition+Session, foo, identity) 
bar 
# Condition Session   Time 
# 1   A  1  100, 200 
# 2   B  2 200, 300, 500 
# 3   A  3   300 
# 4   A  4   200 
bar[1,3] 
# $`0` 
# [1] 100 200 
1

這是一個選項。 (潛在大)需要說明的是,我使用所謂cbind.fill一個(非常有用),但非標定製功能:

> dat <- read.table(text = "|Condition|Session|Time| 
+ |  A|  1| 100| 
+ |  A|  1| 200| 
+ |  B|  2| 200| 
+ |  B|  2| 300| 
+ |  B|  2| 500| 
+ |  A|  3| 300| 
+ |  A|  4| 200|",header = TRUE,sep = "|") 
dat$X <- dat$X.1 <- NULL 

dat$Condition <- factor(dat$Condition,labels = LETTERS[1:2]) 

tmp <- with(dat,split(Time,list(Condition,Session))) 
tmp <- tmp[sapply(tmp,function(x) length(x) > 0)] 
res <- do.call(cbind.fill,tmp) 

nm <- strsplit(names(tmp),split="\\.") 

res <- rbind(as.numeric(sapply(nm,'[',2)),res) 
colnames(res) <- sapply(nm,'[',1) 
> res 
     A B A A 
[1,] 1 2 3 4 
[2,] 100 200 300 200 
[3,] 200 300 NA NA 
[4,] NA 500 NA NA 

cbind.fill核心思想可以this問題被發現。儘管如此,我不會答應完全相同的結果,因爲我在那裏使用了代碼的慷慨修改版。

1
dat <- read.table(text="Condition|Session|Time 
A|  1| 100 
A|  1| 200 
B|  2| 200 
B|  2| 300 
B|  2| 500 
A|  3| 300 
A|  4| 200", header=TRUE,sep="|") 
tapply(dat$Time, paste(dat$Condition, dat$Session, sep="_"), list) 
#---------- 
$A_1 
[1] 100 200 

$A_3 
[1] 300 

$A_4 
[1] 200 

$B_2 
[1] 200 300 500 
#-------------------- 
tdat <-.Last.value 
lmax <- max(sapply(tdat, function(x) length(x))) 
as.data.frame(lapply(tdat, function(x) c(x, rep(NA, lmax- length(x))))) 
#--------------------- 
    A_1 A_3 A_4 B_2 
1 100 300 200 200 
2 200 NA NA 300 
3 NA NA NA 500