用NA替换行中的重复项,保留行中R中的第一个
我正在尝试按行删除重复数据。例如用NA替换行中的重复项,保留行中R中的第一个,r,dplyr,duplicates,R,Dplyr,Duplicates,我正在尝试按行删除重复数据。例如 > head(data_Final) ID Value1 Value2 Value3 Value4 1 a 876 989 989 758 2 b 921 801 971 995 3 c 636 889 7724 95 4 d 999 999 896 999 5 e 2
> head(data_Final)
ID Value1 Value2 Value3 Value4
1 a 876 989 989 758
2 b 921 801 971 995
3 c 636 889 7724 95
4 d 999 999 896 999
5 e 251 254 251 235
6 f 552 100 669 015
我需要这样的结果:
> head(data_Final)
ID Value1 Value2 Value3 Value4
1 a 876 989 NA 758
2 b 921 801 971 995
3 c 636 889 7724 95
4 d 999 NA 896 NA
5 e 251 254 NA 235
6 f 552 100 669 015
我搜索了很多,但结果是在一列中而不是在一行中找到重复的元素。我们可以使用apply循环数值列,并用NA替换重复的元素
或者使用purrr中的pmap
基准
运行它
您可以使用ave:
@是的,我从你那里得到的。我有一些作业。但在这种情况下,它是关于for循环的。在数据帧上应用这些函数可能会变得非常慢。@akrun-我告诉过你,我的答案不是关于替换。它即将申请循环。在R中,有一个神话认为应用函数比for循环更快、更有效。但这根本不是真的。你可以编译for循环,让它更快一点,但无论如何,与apply进行比较是毫无意义的,这就是我的观点。我强烈评论的原因是为了提供正确的信息,而不是别的。谢谢,不过我发现t很快,我可能错了。唯一的问题可能是大容量的内存datasets@akrun啊,这可能是真的,这是内存占用。。。有时应用函数处理一个巨大的数据帧需要30分钟以上。这是真的。。。可能是因为记忆。。。我是生物信息学专业的,有时我们有几百Mb甚至几Gb大小的表。你可以将数据转换为长格式,按ID分组,变异重复值,然后再转换为宽格式。好吧,很久没有见过你使用apply了now@Onyambu就行而言,它更容易表达和获得计算,而不是枢轴/repivot等。我喜欢for循环的优雅,但它只是subjective@akrun是的,我还发现for循环更容易阅读。有时速度会更快,因为在数据帧上使用apply时,通常必须使用t和data.frame才能做到这一点。但正如我所说的,有时随着应用,计算机变得非常慢。当df真的很大的时候,这是一种预感。可能是因为有人在原位改变了这些值……有趣的是使用的是
data_Final[-1] <- t(apply(data_Final[-1], 1,
function(x) replace(x, duplicated(x), NA)))
data_Final
# ID Value1 Value2 Value3 Value4
#1 a 876 989 NA 758
#2 b 921 801 971 995
#3 c 636 889 7724 95
#4 d 999 NA 896 NA
#5 e 251 254 NA 235
#6 f 552 100 669 15
for(i in seq_len(nrow(data_Final))) {
tmp <- data_Final[i, -1]
data_Final[i, -1] <- replace(tmp, duplicated(tmp), NA)
}
library(dplyr)
library(purrr)
data_Final %>%
select(-ID) %>%
pmap_dfr(., ~ c(...) %>%
replace(., duplicated(.), NA)) %>%
bind_cols(select(data_Final, ID), .)
system.time(t(apply(data_Final[-1], 1,
function(x) replace(x, duplicated(x), NA))))
# user system elapsed
# 0.013 0.003 0.015
system.time(for(i in seq_len(nrow(data_Final))) {
tmp <- data_Final[i, -1]
data_Final[i, -1] <- replace(tmp, duplicated(tmp), NA)
}
)
# user system elapsed
# 0.014 0.004 0.018
data_Final <- structure(list(ID = c("a", "b", "c", "d", "e", "f"),
Value1 = c(876L,
921L, 636L, 999L, 251L, 552L), Value2 = c(989L, 801L, 889L, 999L,
254L, 100L), Value3 = c(989L, 971L, 7724L, 896L, 251L, 669L),
Value4 = c(758L, 995L, 95L, 999L, 235L, 15L)), class = "data.frame",
row.names = c("1",
"2", "3", "4", "5", "6"))
replace.dup <- function(x, val=NA) {
x[duplicated(x)] <- val
x
}
replace.row.wise.dups <- function(df, val=NA) {
for (i in 1:nrow(df)) {
df[i, ] <- replace.dup(unlist(df[i, , drop=T]), val)
}
df
}
text <- " ID Value1 Value2 Value3 Value4
1 a 876 989 989 758
2 b 921 801 971 995
3 c 636 889 7724 95
4 d 999 999 896 999
5 e 251 254 251 235
6 f 552 100 669 015"
txt <- gsub("\ +", "\t", text)
df <- read.delim(text = txt, sep="\t", row.names=1, stringsAsFactors=FALSE)
replace.row.wise.dups(df, NA)
# ID Value1 Value2 Value3 Value4
# 1 a 876 989 <NA> 758
# 2 b 921 801 971 995
# 3 c 636 889 7724 95
# 4 d 999 <NA> 896 <NA>
# 5 e 251 254 <NA> 235
# 6 f 552 100 669 15
# from @akrun
replace.row.wise.dup.1 <- function(df, val=NA) {
as.data.frame(t(apply(df, 1, function(x) replace(x, duplicated(x), NA))))
}
require(microbenchmark)
mbm <- microbenchmark("apply" = replace.row.wise.dups.1(df, NA),
"for-loop" = replace.row.wise.dups(df, NA),
times = 1000)
# > mbm
# Unit: microseconds
# expr min lq mean median uq max neval
# apply 600.950 623.9905 673.0897 632.4485 645.910 3668.063 1000
# for-loop 696.792 727.8785 791.7684 754.1875 772.129 2491.147 1000
data_Final[-1]<-ave(unlist(data_Final[-1]), row(data_Final[-1]),
FUN = function(x)`is.na<-`(x,duplicated(x)))
data_Final
ID Value1 Value2 Value3 Value4
1 a 876 989 NA 758
2 b 921 801 971 995
3 c 636 889 7724 95
4 d 999 NA 896 NA
5 e 251 254 NA 235
6 f 552 100 669 15