R 中的唯一对,忽略顺序

C_Z*_*_Z_ 3 r

假设我有一个这样的数据框:

dat<-data.frame(c("a", "b", "c"), c("b", "a", "d"), stringsAsFactors=F)
colnames(dat)<-c("V1", "V2")
dat
#    V1  V2
# 1   a   b
# 2   b   a
# 3   c   d
Run Code Online (Sandbox Code Playgroud)

我想要做的是,每一行都是一对,生成所有唯一的对,忽略顺序。所以我的输出会像

unique_pairs(dat$V1, dat$V2)

# Output
#   V1  V2
# 1  a   b
# 2  c   d
Run Code Online (Sandbox Code Playgroud)

这样做的最有效方法是什么?

jos*_*ber 5

一种选择(由@bgoldst 回答)是使用apply. 但是,对于使用单个调用pminpmax而不是使用多次调用在行上操作的大型数据帧,我们将获得更好的性能sort

# Make a larger data frame by sampling
set.seed(144)
dat.large <- dat[sample(nrow(dat), 10000, replace=T),]

# Row-wise and column-wise computations
rowwise <- function(dat) unique(t(apply(dat, 1, sort)))
colwise <- function(dat) unique(cbind(pmin(dat[,1], dat[,2]), pmax(dat[,1], dat[,2])))
all.equal(unname(rowwise(dat.large)), unname(colwise(dat.large)))
# [1] TRUE

# Compare performance
library(microbenchmark)
microbenchmark(rowwise(dat.large), colwise(dat.large))
# Unit: milliseconds
#                expr       min        lq      mean    median        uq      max neval
#  rowwise(dat.large) 465.45604 523.49464 564.91541 559.14461 595.58961 805.7982   100
#  colwise(dat.large)  33.69199  42.91692  50.87839  47.70415  53.06705 122.4459   100
Run Code Online (Sandbox Code Playgroud)

如您所见,对于 10000 行输入,按列操作的速度大约快 10 倍,这显示了在 R 中计算时矢量化的强大功能。显然,从 500 毫秒到 50 毫秒的加速可能不是什么大问题,但如果您在处理大型数据集时,矢量化方法可能更可取。