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 中实现这一点?

4

4 回答 4

1

首先,a 的每一列都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
于 2012-11-19T20:11:58.280 回答
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可以在这个问题中找到。不过,我不会保证相同的结果,因为我在那里使用的是经过大量修改的代码版本。

于 2012-11-19T20:15:28.577 回答
1

我提供了另一种可能的解决方案,使用ddplyfrom the plyrpackage 和dcastfrom 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   
于 2012-11-19T21:26:11.710 回答
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
于 2012-11-20T03:42:52.200 回答