2014-10-22 51 views
3

我有一个数据表,带有一个键ID和一个带有文本值的列。 密钥ID不是唯一的(某些行共享相同的ID;可能有1到8行具有相同的ID)。我想要一个数据表,具有唯一的密钥ID和8列。R数据表的特殊整形

例如,我有什么:

require(data.table) 
set.seed(1) 
out<-data.table(id=c(rep("id1",3),rep("id2",2),"id3"),value=paste("value",round(rnorm(6,0,100)))) 
out 
#  id  value 
# 1: id1 value 49 
# 2: id1 value 74 
# 3: id1 value 58 
# 4: id2 value -31 
# 5: id2 value 151 
# 6: id3 value 39 

所需的输出:

data.table(id=c("id1","id2","id3"),value1=c("value -63","value 160","value -82"),value2=c("value 18","value 33",NA),value3=c("value -84",NA,NA)) 
# id value1 value2 value3 
#1: id1 value -63 value 18 value -84 
#2: id2 value 160 value 33  NA 
#3: id3 value -82  NA  NA 
+1

(+1)对于初学者来说非常有趣的问题。我希望所有新手都像你一样...... – 2014-10-22 11:51:05

回答

0

你会考虑aggregate

aggregate(value~id,data=out,FUN=paste,collapse=" ") 

id      value 
1 id1 value -63 value 18 value -84 
2 id2   value 160 value 33 
3 id3     value -82 

这不等同于您所需的输出,但它无论如何,这个技巧都能做到

+0

请注意,您可以通过在'collapse'参数中添加一个字符来更改分隔符。 – 2014-10-22 11:18:39

+0

你有没有注意到这是一个'data.table'问题?为什么他会用'聚合'?他可以用'data.table'做同样的事情,比如out [,paste(value,collapse =“”),by = id]',但是没有达到他想要的输出方式 – 2014-10-22 11:23:42

+0

我不知道。猜猜你每天都会学到新的东西。 – 2014-10-22 11:25:06

4

你可以尝试:(setnames部分由@大卫Arenburg贡献)

res <- setnames(dcast.data.table(out[, N:=1:.N,by=id], id~N, value.var="value"), 
                2:4, paste0("value", 1:3)) 
res 
#  id value1 value2  value3 
# 1: id1 value -63 value 18 value -84 
# 2: id2 value 160 value 33  NA 
# 3: id3 value -82  NA  NA 

或紧凑版本建议由@大卫Arenburg

dcast.data.table(out[, N := paste0('value', 1:.N), by = id], 
            id ~ N, value.var = "value") 
+0

不错的一个 – 2014-10-22 11:28:12

+0

@David Arenburg感谢您的编辑。我想我需要使用'setnames'来获取正确的名称。 – akrun 2014-10-22 11:29:40

+1

我不认为那么重要,可以做一些像'res < - setnames(dcast.data.table(out [,N:= 1:.N,by = id],id〜N,value.var =“value”),2:4,paste0(“value”,1:3))' – 2014-10-22 11:31:53