Используется combn
для ускорения:
library(RcppAlgos)
f_no_loop = function(DF) {
n = nrow(DF)
DF = as.matrix(DF)
ind <- RcppAlgos::comboGeneral(n, 2)
comp1 <- rowSums(abs(DF[ind[, 1], ] - DF[ind[, 2], ]) <= 0.5)!=0
nx <- sum(comp1)
ns <- sum(rowSums(DF[ind[, 1], ] > DF[ind[, 2], ])[!comp1] != 1)
nd <- nrow(ind) - ns - nx
return(c(ns = ns, nx = nx, nd = nd))
}
f_no_loop(V)
Также вам следует пересмотреть циклы. Ваш оригинальный подход выиграл бы от двух незначительных модификаций: 1) подмножества векторов вместо data.frames и 2) использование rcpp . @Jogo уже продемонстрировал первую часть - вот Rcpp
версия того же самого:
library(Rcpp)
Rcpp::cppFunction('
IntegerVector nsxd_rcpp(IntegerVector V1, IntegerVector V2){
int ns = 0; int nx = 0; int nd = 0;
IntegerVector ret(3);
for (int a = 0; a < V1.size() - 1; a++){
for (int b = a + 1; b < V1.size(); b++){
if ((abs(V1[a] - V1[b]) <= 0.5) | (abs(V2[a] - V2[b]) <= 0.5)) {
nx++;
} else {
if (((V1[a] > V1[b]) + (V2[a] > V2[b])) == 1) {
nd++;
} else {
ns++;
}
}
}
}
ret[0] = ns;
ret[1] = nx;
ret[2] = nd;
ret.names() = CharacterVector::create("ns", "nx", "nd");
return(ret);
}'
)
Производительность
set.seed(42)
n <- 1000
V <- data.frame(name1=sample.int(30, n, repl=TRUE), name2=sample.int(30, n, repl=TRUE))
bench::mark(
nsxd(V[, 1], V[, 2]),
f_no_loop(V),
nsxd2(V[, 1], V[, 2]),
nsxd_rcpp(V[, 1], V[, 2])
)
#1,000 rows
expression min median `itr/sec` mem_alloc `gc/sec`
<bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
1 nsxd(V[, 1], V[, 2]) 674.93ms 674.93ms 1.48 0B 19.3
2 f_no_loop(V) 51.36ms 58.89ms 15.4 62.4MB 40.3
3 nsxd2(V[, 1], V[, 2]) 43.68ms 47.45ms 21.5 43.22MB 35.2
4 nsxd_rcpp(V[, 1], V[, 2]) 4.84ms 4.86ms 205. 2.49KB 0
#10,000 rows
# A tibble: 3 x 13
expression min median `itr/sec` mem_alloc `gc/sec`
<bch:expr> <bch:t> <bch:tm> <dbl> <bch:byt> <dbl>
1 f_no_loop(V) 6.11s 6.11s 0.164 6.1GB 1.47
2 nsxd2(V[, 1], V[, 2]) 3.89s 3.89s 0.257 4.14GB 1.29
3 nsxd_rcpp(V[, 1], V[, 2]) 479ms 480.03ms 2.08 2.49KB 0
#100,000 rows
# A tibble: 1 x 13
expression min median `itr/sec` mem_alloc `gc/sec` n_itr
<bch:expr> <bch> <bch:> <dbl> <bch:byt> <dbl> <int>
1 nsxd_rcpp(V[, 1], V[, 2]) 47.5s 47.5s 0.0211 2.49KB 0 1