这个怎么样?
df[, 2:4][t(apply(df[,2:4], 1, duplicated))] <- NA
编辑:一个更快的基础解决方案:
for (i in 2:(ncol(df)-1)) {
for (j in (i+1):ncol(df)) {
chk <- df[[i]] == df[[j]]
df[[j]][chk] <- NA
}
}
以下是对上述两种方法的基准测试结果,同时也包括了AnandaMahto使用的reshape2
和data.table
方法在更大数据上的表现。使用正确的i
和j
索引的for-loop
似乎是最快速的。
基准测试结果:
require(microbenchmark)
microbenchmark(ar.f <- arun.f(df), ar.s <- arun.s(df),
an.f <- ananda.ave(df),
an.s <- ananda.dt(copy(DT)), times=10)
创建数据:
set.seed(1234)
df <- cbind(data.frame(ID = rep(letters[1:20], each=1e4)), stringsAsFactors=FALSE),
matrix(sample(1:10, 6 * 1e5, replace=TRUE), ncol=3))
names(df)[2:4] <- paste0("code", 1:3)
我的第一个版本:
arun.f <- function(df) {
df[, 2:4][t(apply(df[,2:4], 1, duplicated))] <- NA
df
}
My second version:
arun.s <- function(df) {
for (i in 2:(ncol(df)-1)) {
for (j in (i+1):ncol(df)) {
chk <- df[[i]] == df[[j]]
df[[j]][chk] <- NA
}
}
df
}
Ananda的ave
+reshape2
解决方案:
library(reshape2)
ananda.ave <- function(df) {
df$ID2 <- with(df, ave(ID, ID, FUN = seq_along))
m.df <- melt(df, id.vars=c("ID", "ID2"))
m.df[duplicated(m.df[setdiff(names(m.df), "variable")]), "value"] <- NA
dcast(m.df, ID + ID2 ~ variable)
}
Ananda的data.table
解决方案:
(稍作修改以更加优化)
library(data.table)
DT <- data.table(df)
ananda.dt <- function(dt) {
temp <- dt[, list(ID2 = 1:.N, Value = unlist(.SD, use.names=FALSE)), by ="ID"]
temp[duplicated(temp), Value := NA]
out <- setnames(temp[, as.list(Value), by=list(ID, ID2)], 3:5, paste0("code", 1:3))
}
for
得到了胜利(但原始答案更具表现力)。 - Matthew Lundberg