R 寻找与位置无关的唯一组合

R 寻找与位置无关的唯一组合,r,duplicates,combinations,R,Duplicates,Combinations,我相信这很简单,但我有一个数据框 df <- data.frame(a = c(1, 2, 3), b = c(2, 3, 1), c = c(3, 1, 4)) 我试过了 unique(df[c('a', 'b', 'c')]) 但它认为(1,2,3)是(2,3,1)中唯一的,这是我不想要的 可能是这样的 indx <- !duplicated(t(apply(df,

我相信这很简单,但我有一个数据框

      df <- data.frame(a = c(1, 2, 3),
                       b = c(2, 3, 1),
                       c = c(3, 1, 4))
我试过了

    unique(df[c('a', 'b', 'c')])

但它认为(1,2,3)是(2,3,1)中唯一的,这是我不想要的

可能是这样的

indx <- !duplicated(t(apply(df, 1, sort))) # finds non - duplicates in sorted rows
df[indx, ] # selects only the non - duplicates according to that index
#   a b c
# 1 1 2 3
# 3 3 1 4

indx作为一种替代方法,软件包
sets
提供了一种快速检查集合相等性的方法:

library(sets)
df.sets <- apply(df, 1, as.set)
#[[1]]
#{1, 2, 3}
#[[2]]
#{1, 2, 3}
#[[3]]
#{1, 3, 4}
df[!duplicated(df.sets),]
#  a b c
#1 1 2 3
#3 3 1 4
库(套)

df.sets如果你的data.frame很大,速度可能是你的问题。使用以下方法可以更快地找到重复集

让我们为每行中的每个可能值分配一个素数,并计算每行的乘积。例如,对于给定的
df
我们可以接受
primenums=c(2,3,5,7)
并计算产品
c(30,30,70)
。然后,此乘积向量中的重复项对应于data.frame中的重复集。由于乘法的计算速度比任何排序都快,因此可以提高效率。 代码如下

require("numbers")
primenums <- Primes(100)[1:4]
dfmult <- apply(as.matrix(df), 1, function(z) prod(primenums[z]) )
my_indx <- !duplicated(dfmult)
df[my_indx,]
现在,当data.frame准备就绪时,我们可以测试不同的算法

system.time(indx <- !duplicated(t(apply(df, 1, sort))) )
#   user  system elapsed 
# 119.75    0.06  120.03
# doesn't impress, frankly speaking

library(sets)
system.time(indx <- !duplicated(apply(df, 1, as.set)) )
#  user  system elapsed 
# 91.60    0.00   91.89
# better, but we want faster! =)

# now lets check out the method with prime numbers
primenums <- Primes(100)[1:20]
# [1]  2  3  5  7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71
system.time({
  dfmult <- apply(as.matrix(df), 1, function(z) prod(primenums[z]) )
  my_indx <- !duplicated(dfmult) })
# user  system elapsed 
# 6.44    0.16    6.61
# not bad, isn't it? but lets compare results
identical(indx, my_indx)
# [1] TRUE

# So, if there is no difference, why wait more? ;)
如果我们有很多列或者非常不同的变量呢?在这种情况下,我们可以使用
sum(log())
来代替
prod()。看看这个

pr <- Primes(5e7)
length(pr)   
# [1] 3001134
system.time(N <- sum(log(pr)))
# user  system elapsed 
# 0.12    0.00    0.13
N
# [1] 49993718

pr这是一个很好的方法,虽然不确定你在这里做
as.matrix(df)
是否有点作弊。+1非常快,我喜欢使用素数分解的想法,但这种方法有两个局限性:1)如果有大量列使用素数的乘积将不起作用(例如
prod(素数(200))
等于
prod(Primes(201))
)和2)如果数据帧包含大量不同的元素,它将不起作用(因为您需要为每个元素生成一个prime,这可能会很麻烦,而且还因为产品不会像前一点那样由计算机区分)为了保持冷静,而不是像.matrix那样做
as.code>,我们可以做
apply(df,2,function(colmn)as.integer(factor(colmn,levels=unique)(c(as.matrix(df ')))
)。这会比较慢,但不会太多,我明天会给出时间和更新答案,因为我现在不在电脑上。我同意,素数的使用有局限性,但也许你可以尝试不同的r软件包,它允许处理非常大的数字?编辑了我的答案,发展了这个想法
system.time(indx <- !duplicated(t(apply(df, 1, sort))) )
#   user  system elapsed 
# 119.75    0.06  120.03
# doesn't impress, frankly speaking

library(sets)
system.time(indx <- !duplicated(apply(df, 1, as.set)) )
#  user  system elapsed 
# 91.60    0.00   91.89
# better, but we want faster! =)

# now lets check out the method with prime numbers
primenums <- Primes(100)[1:20]
# [1]  2  3  5  7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71
system.time({
  dfmult <- apply(as.matrix(df), 1, function(z) prod(primenums[z]) )
  my_indx <- !duplicated(dfmult) })
# user  system elapsed 
# 6.44    0.16    6.61
# not bad, isn't it? but lets compare results
identical(indx, my_indx)
# [1] TRUE

# So, if there is no difference, why wait more? ;)
system.time({
  dfmult <- apply(
    apply(df, 2, function(colmn) as.integer(factor(colmn, 
                                                   levels = unique(c(as.matrix(df)))))),
    1, function(z) prod(primenums[z]) )
  my_indx <- !duplicated(dfmult) })
#  user  system elapsed 
# 27.48    0.34   27.84
# is distinctly slower but still much faster then previous methods
pr <- Primes(5e7)
length(pr)   
# [1] 3001134
system.time(N <- sum(log(pr)))
# user  system elapsed 
# 0.12    0.00    0.13
N
# [1] 49993718