更新:更快的选择
通过使用矩阵索引,您将获得最佳速度。这是一个示例(带有注释,因此您可以看到发生了什么)。
## Assuming this is your starting data
dat <- read.table(text="name1 a b c d NA NA\nname2 a c e g i NA\nname3 t j i m n z")
rownames(dat) <- dat$V1
dat$V1 <- NULL
## Convert the data.frame into a single character vector
A <- unlist(lapply(dat, as.character), use.names = FALSE)
## Identify the unique levels
levs <- sort(unique(na.omit(A)))
## Get the index position for the Row/Column combination
## that needs to be recoded as "1"
Rows <- rep(sequence(nrow(dat)), ncol(dat))
Cols <- match(A, levs)
## Create an empty matrix
m <- matrix(0, nrow = nrow(dat), ncol = length(levs),
dimnames = list(rownames(dat), levs))
## Use matrix indexing to replalce the relevant values with 1
m[cbind(Rows, Cols)] <- 1L
m
# a b c d e g i j m n t z
# name1 1 1 1 1 0 0 0 0 0 0 0 0
# name2 1 0 1 0 1 1 1 0 0 0 0 0
# name3 0 0 0 0 0 0 1 1 1 1 1 1
基准
在创建30000data.table
行版本的初始data.frame
. 结果如下:
dat2 <- dat ## A backup
dat <- do.call(rbind, replicate(10000, dat, simplify = FALSE))
dim(dat)
# [1] 30000 6
library(microbenchmark)
microbenchmark(AM(), AMDT(), RS(), times = 10)
# Unit: milliseconds
# expr min lq median uq max neval
# AM() 44.30915 56.21873 57.95815 86.1518 265.3053 10
# AMDT() 231.71928 245.64236 291.19601 376.8983 515.8216 10
# RS() 4414.01127 4698.47293 4731.72877 5484.6185 5726.8092 10
矩阵索引显然获胜,但鉴于data.table
完成工作的语法简洁,我更喜欢这种方法!@Arun 将 Hadley 的作品与“reshape2”一起移植到了data.table
!!!
原始答案
这是一个“data.table”替代方案。它至少需要 1.8.11 版的“data.table”。
加载所需的包
library(data.table)
library(reshape2)
packageVersion("data.table")
# [1] ‘1.8.11’
melt
和cast
你的data.table
DT <- data.table(dat, keep.rownames=TRUE)
dcast.data.table(melt(DT, id.vars="rn"), rn ~ value)
# Aggregate function missing, defaulting to 'length'
# rn NA a b c d e g i j m n t z
# 1: name1 0 1 1 1 1 0 0 0 0 0 0 0 0
# 2: name2 0 1 0 1 0 1 1 1 0 0 0 0 0
# 3: name3 0 0 0 0 0 0 0 1 1 1 1 1 1