我有一个这样的数据表:
data.table(a=rep(c("xx", "yy"), each=4), b=rep(c("zz", "nn"), each=2), vals=10:17)
a b vals
1: xx zz 10
2: xx zz 11
3: xx nn 12
4: xx nn 13
5: yy zz 14
6: yy zz 15
7: yy nn 16
8: yy nn 17
这是我想要的,因为当导出到excel然后导出到单词时,它在表中看起来更好(我知道,从不使用excel ...):
a b vals
1: xx zz 10
2: NA NA 11
3: NA nn 12
4: NA NA 13
5: yy zz 14
6: NA NA 15
7: NA nn 16
8: NA NA 17
编辑:忘记说如果重复出现一个数字值,则不应将其更改为NA,而只能更改为字符列。
答案 0 :(得分:4)
使用rleid
中的data.table
,我们可以创建一个函数
library(data.table)
replace_duplicated <- function(x) {
replace(x, duplicated(rleid(x)), NA)
}
现在将其应用于选定的列(感谢@markus)
cols = names(df)[sapply(df, is.character)]
df[,(cols) := lapply(.SD, replace_duplicated ), .SDcols = cols]
df
# a b vals
#1: xx zz 10
#2: <NA> <NA> 11
#3: <NA> nn 12
#4: <NA> <NA> 13
#5: yy zz 14
#6: <NA> <NA> 15
#7: <NA> nn 16
#8: <NA> <NA> 17
在dplyr
中,我们可以使用mutate_if
library(dplyr)
df %>% mutate_if(is.character, replace_duplicated)
或mutate_at
df %>% mutate_at(cols, replace_duplicated)
答案 1 :(得分:4)
我们可以使用set
中的data.table
通过引用进行更新
nm1 <- names(dt)[1:2]
for(j in nm1) set(dt, i = which(duplicated(rleid(dt[[j]]))), j = j, value = NA)
dt
# a b vals
#1: xx zz 10
#2: <NA> <NA> 11
#3: <NA> nn 12
#4: <NA> <NA> 13
#5: yy zz 14
#6: <NA> <NA> 15
#7: <NA> nn 16
#8: <NA> <NA> 17
答案 2 :(得分:2)
使用shift
添加另一种方法,并提供一些参考时间:
set.seed(0L)
sz <- 1e7
DT <- data.table(a=sample(LETTERS, sz, TRUE), b=sample(LETTERS, sz, TRUE))
#DT <- data.table(a=rep(c("xx", "yy"), each=4), b=rep(c("zz", "nn"), each=2), vals=10:17)
DT1 <- copy(DT)
DT2 <- copy(DT)
cols <- c("a","b")
mtd0 <- function() {
DT[,(cols) := lapply(.SD, function(x)
replace(x, duplicated(rleid(x)), NA_character_)) , .SDcols = cols]
}
mtd1 <- function() {
for(j in cols)
set(DT1, i=DT1[, which(get(j)==shift(get(j), 1L))], j=j, value=NA_character_)
}
mtd2 <- function() {
for(j in cols)
set(DT2, i=which(duplicated(rleid(DT2[[j]]))), j=j, value=NA_character_)
}
library(microbenchmark)
microbenchmark(mtd0(), mtd1(), mtd2(), times=3L)
identical(DT, DT1)
#[1] TRUE
identical(DT1, DT2)
#[1] TRUE
时间:
Unit: milliseconds
expr min lq mean median uq max neval cld
mtd0() 1372.4244 1405.1756 1448.8020 1437.9269 1486.9909 1536.0549 3 b
mtd1() 280.7695 281.2639 305.5433 281.7583 317.9303 354.1022 3 a
mtd2() 1200.5236 1224.5174 1339.0146 1248.5112 1408.2601 1568.0090 3 b
答案 3 :(得分:0)
您可以快速循环进行此操作:
df <- data.frame(a=rep(c("xx", "yy"), each=4), b=rep(c("zz", "nn"), each=2), vals=10:17)
for(i in 1:2){
df[,i][duplicated(df[,i])] <-NA
}