比较两个数据框,与列顺序无关,以获得非重复行
Compare two data frames, column-order-independent, to get non-duplicated rows
我想比较两个数据框并检查是否有重复的行。
我们假设列的顺序无关紧要,所以如果 df1 看起来像这样:
V2 V3
71 78
90 13
12 67
56 32
像这样的 df2:
V2 V3
89 45
77 88
78 71
90 13
那么来自两个 df 的非重复行将是:
12 67
56 32
89 45
77 88
我怎样才能轻松实现这个目标?
你可以试试
df3 <- rbind(df1, df2)
df4 <- df3
df3[] <- cbind(do.call(pmax, df3), do.call(pmin, df3))
df4[!(duplicated(df3)|duplicated(df3, fromLast=TRUE)),]
# V2 V3
#3 12 67
#4 56 32
#5 89 45
#6 77 88
下面提供的解决方案适用于您的示例数据。对于相当大的数据集,这种方法可能效率低下。再一次,计算机时间很便宜。 :)
df1 <- read.table(text = " V2 V3
71 78
90 13
12 67
56 32", header = TRUE)
df2 <- read.table(text = "V2 V3
89 45
77 88
78 71
90 13", header = TRUE)
throwoutFunction <- function(x, ca) {
find.duplicates <- apply(ca, MARGIN = 1, FUN = function(y, x) y %in% x, x = x)
filter.duplicates <- apply(find.duplicates, MARGIN = 2, all)
if (any(filter.duplicates)) {
return(data.frame(V2 = NA, V3 = NA))
} else {
data.frame(V2 = x[1], V3 = x[2])
}
}
out1 <- do.call("rbind", apply(df1, MARGIN = 1, FUN = throwoutFunction, ca = df2))
out2 <- do.call("rbind", apply(df2, MARGIN = 1, FUN = throwoutFunction, ca = df1))
out <- na.omit(rbind(out1, out2))
rownames(out) <- 1:nrow(out)
out
V2 V3
1 12 67
2 56 32
3 89 45
4 77 88
这是一个 dplyr 解决方案,在较大的数据集上可能会很快
df1 <- data_frame( v1 = c(71,90,12,56), v2 = c(78,13,67,32))
df2 <- data_frame( v1 = c(89,77,78,90), v2 = c(45,88,71,13) )
df3 <- bind_rows(df1, df2)
df3 %>%
rowwise() %>%
mutate(key = paste0( min(v1, v2), max(v1, v2))) %>%
group_by(key) %>%
mutate( size = n()) %>%
filter( size == 1)
此解决方案仅适用于两个分组变量,要将其扩展到多个变量,您基本上只需要调整制造密钥的方式即可。
编辑:根据下面的评论,我误解了这个问题。
我想比较两个数据框并检查是否有重复的行。 我们假设列的顺序无关紧要,所以如果 df1 看起来像这样:
V2 V3
71 78
90 13
12 67
56 32
像这样的 df2:
V2 V3
89 45
77 88
78 71
90 13
那么来自两个 df 的非重复行将是:
12 67
56 32
89 45
77 88
我怎样才能轻松实现这个目标?
你可以试试
df3 <- rbind(df1, df2)
df4 <- df3
df3[] <- cbind(do.call(pmax, df3), do.call(pmin, df3))
df4[!(duplicated(df3)|duplicated(df3, fromLast=TRUE)),]
# V2 V3
#3 12 67
#4 56 32
#5 89 45
#6 77 88
下面提供的解决方案适用于您的示例数据。对于相当大的数据集,这种方法可能效率低下。再一次,计算机时间很便宜。 :)
df1 <- read.table(text = " V2 V3
71 78
90 13
12 67
56 32", header = TRUE)
df2 <- read.table(text = "V2 V3
89 45
77 88
78 71
90 13", header = TRUE)
throwoutFunction <- function(x, ca) {
find.duplicates <- apply(ca, MARGIN = 1, FUN = function(y, x) y %in% x, x = x)
filter.duplicates <- apply(find.duplicates, MARGIN = 2, all)
if (any(filter.duplicates)) {
return(data.frame(V2 = NA, V3 = NA))
} else {
data.frame(V2 = x[1], V3 = x[2])
}
}
out1 <- do.call("rbind", apply(df1, MARGIN = 1, FUN = throwoutFunction, ca = df2))
out2 <- do.call("rbind", apply(df2, MARGIN = 1, FUN = throwoutFunction, ca = df1))
out <- na.omit(rbind(out1, out2))
rownames(out) <- 1:nrow(out)
out
V2 V3
1 12 67
2 56 32
3 89 45
4 77 88
这是一个 dplyr 解决方案,在较大的数据集上可能会很快
df1 <- data_frame( v1 = c(71,90,12,56), v2 = c(78,13,67,32))
df2 <- data_frame( v1 = c(89,77,78,90), v2 = c(45,88,71,13) )
df3 <- bind_rows(df1, df2)
df3 %>%
rowwise() %>%
mutate(key = paste0( min(v1, v2), max(v1, v2))) %>%
group_by(key) %>%
mutate( size = n()) %>%
filter( size == 1)
此解决方案仅适用于两个分组变量,要将其扩展到多个变量,您基本上只需要调整制造密钥的方式即可。
编辑:根据下面的评论,我误解了这个问题。