我的数据结构如下所示
id year club
"A" "2010" "C1"
"B" "2010" "C1"
"C" "2010" "C2"
"A" "2011" "C1"
"B" "2011" "C2"
等。我的问题是逐年创建一个矩阵,每个独特的个体固定在一行,每个独特的俱乐部固定在一列。如果在给定年份中,个人访问俱乐部,则相应的交叉单元格的值为1,否则为0.
非常感谢任何帮助。
由于 阿努普
答案 0 :(得分:3)
在基数R中,我会使用by
和xtabs
:
by(dat, dat$year, with, as.matrix(xtabs(~ id + club) * 1L))
它返回一个矩阵列表(每年一个)。另外,我建议不要乘以1L
来返回布尔矩阵。
Edit1:根据建议,您还可以非常轻松地创建列联表:
table(dat[c("id", "club", "year")])
Edit2:我看到你对里卡多回答的评论,也许这就是你要找的:
library(plyr)
ddply(dat, .(year, id), with, 1L * (table(club) > 0))
# year id C1 C2
# 1 2010 A 1 0
# 2 2010 B 1 0
# 3 2010 C 0 1
# 4 2011 A 1 0
# 5 2011 B 0 1
您可能还想使用.drop = FALSE
来获取所有(6)可能的年/ ID组合:
ddply(dat, .(year, id), with, 1L * (table(club) > 0), .drop = FALSE)
# year id C1 C2
# 1 2010 A 1 0
# 2 2010 B 1 0
# 3 2010 C 0 1
# 4 2011 A 1 0
# 5 2011 B 0 1
# 6 2011 C 0 0
答案 1 :(得分:2)
这个单行解决方案输出单个数据帧而不是像迄今为止发布的其他解决方案那样的单独矩阵。它需要reshape2
包,如果你之前从未使用它,对于这类事情非常有用。
require(reshape2)
df = data.frame(id=c('a','b','c','a','b')
,year=c(2010,2010,2010,2011,2011)
,club=c('c1','c1','c2','c1','c2')
)
result = dcast(df, year + id ~ club, fun.aggregate=length, drop=F)
> result
year id c1 c2
1 2010 a 1 0
2 2010 b 1 0
3 2010 c 0 1
4 2011 a 1 0
5 2011 b 0 1
6 2011 c 0 0 # If you don't want this record, use: drop=T
答案 2 :(得分:0)
基于注释,合适的格式是三维数组或data.frames / data.tables列表。
library(data.table)
DT <- data.table
### create a template matrix
# find all unique ID's and unique Club's
ids <- unique(DT$id)
clubs <- unique(DT$club)
# matrix template based on the number of ids & clubs
mat.template <- matrix(0L, nrow=length(ids), ncol=length(clubs), dimnames=list(ids, clubs))
# iterate over the unique values of year
DT <- data.table(dat, key="id,club")
res <- lapply(unique(DT$year), function(y) {
# index the matrix by the DT where y == year. Set those values to 1
mat <- copy(mat.template)
mat[as.matrix(DT[y==year, list(id, club)])] <- 1
mat
})
setattr(res, "names", unique(DT$year))
res
$`2010`
C1 C2
A 1 0
B 1 0
C 0 1
$`2011`
C1 C2
A 1 0
B 0 1
C 0 0