Как использовать R для получения последовательности (1,2,3 ... n, 2,3 ... n, 3,4..n ... n-1, n) - PullRequest
0 голосов
/ 13 сентября 2018

Я не знаю, как это называется, может быть вложенная арифметическая прогрессия? Если n является целым числом, скажем, n = 50, то, что я хотел бы, это

 (1,2,3...n,2,3...n,3,4..n...n-1,n)

это как конкатенация

 1:n, 2:n, ...,n-1:n

Есть ли простой способ сделать это? Спасибо!

Ответы [ 3 ]

0 голосов
/ 13 сентября 2018

Субъект говорит, что последняя подпоследовательность - n, но основная часть вопроса говорит, что это (n-1):n. Я предположил (n-1):n, но чтобы получить другое, просто измените каждый n-1 в коде на n и каждые 2 в коде на 1.

1) lapply Предполагая, что мы хотим, чтобы 1: n, 2: n, ..., (n-1): n перебирали начальное значение каждой подпоследовательности следующим образом:

n <- 4
unlist(lapply(seq_len(n-1), seq, n))
##  [1] 1 2 3 4 2 3 4 3 4

2) последовательность Другой подход заключается в преобразовании sequence(seq(n, 2)) следующим образом:

s <- sequence(seq(n, 2))
s + cumsum(s == 1) - 1
## [1] 1 2 3 4 2 3 4 3 4

3) наружный

m <- outer(seq_len(n), seq_len(n-1), ">=") * seq(n)
m[m > 0]
## [1] 1 2 3 4 2 3 4 3 4

3a) Этот вариант (3) также работает:

m <- outer(seq_len(n), seq_len(n-1), "+") - 1
m[m <= n]
## [1] 1 2 3 4 2 3 4 3 4

4) Уменьшить

f <- function(x, y) c(x, seq(y, n))
Reduce(f, 1:(n-1), c())
## [1] 1 2 3 4 2 3 4 3 4

5) Рекурсия

Recurse <- function(v) {
  if (length(v) > 2) c(v, Recall(tail(v, -1))) else v
}
Recurse(1:n)
## [1] 1 2 3 4 2 3 4 3 4
0 голосов
/ 13 сентября 2018

Использование Rcpp

library(Rcpp)

cppFunction('Rcpp::NumericVector mySeq( int n ) {
  Rcpp::IntegerVector vec = seq(0, n);
  int total_n = sum( vec );
  Rcpp::NumericVector out(total_n);

  size_t i, j;
  int idx = 0;
  int x = 1;
  for( i = 0; i < n; i++ ) {
    x = i + 1;
    for( j = i; j < n; j++) {
      out[idx] = x;
      x++;
      idx++;
    }
  }
  return out;
}')

mySeq(5)
#  [1] 1 2 3 4 5 2 3 4 5 3 4 5 4 5 5

mySeq(10)
# [1]  1  2  3  4  5  6  7  8  9 10  2  3  4  5  6  7  8  9 10  3  4  5  6  7  8  9 10  4  5  6  7  8  9 10  5  6  7  8
# [39]  9 10  6  7  8  9 10  7  8  9 10  8  9 10  9 10 10

И как всегда с этими вариантами ответов, вот эталон

library(microbenchmark)

n <- 10000

microbenchmark(
  rcpp = { mySeq(n) },
  lapply = { lapn(n) },
  sequence = { seqn(n) },
  outer = { outn(n) },
  outer2 = { outn2(n) },
  # reduce = { reducen(n) },   ## takes too long
  # recurse = { recursen(n) }, ## takes too long
  times = 10
)

# Unit: milliseconds
#     expr       min        lq      mean    median        uq       max neval
#     rcpp  213.9762  220.3786  245.6753  230.6847  262.8544  326.5764    10
#   lapply  250.5695  260.5681  288.2523  278.9582  302.9768  367.5507    10
# sequence 1356.2691 1430.5877 1472.6946 1455.7467 1485.3578 1753.4076    10
#    outer 2381.8864 2459.8159 2497.1630 2478.9865 2526.9577 2662.0489    10
#   outer2 2509.8079 2531.1497 2651.6906 2636.3873 2785.3693 2820.2356    10

Функции

lapn <- function(n) { unlist(lapply(seq_len(n-1), seq, n)) }

seqn <- function(n) {
  s <- sequence(seq(n, 2))
  s + cumsum(s == 1) - 1
  return(s)
}
outn <- function(n) {
  m <- outer(seq_len(n), seq_len(n-1), ">=") * seq(n)
  m[m > 0]
}
outn2 <- function(n) {
  m <- outer(seq_len(n), seq_len(n-1), "+") - 1
  m[m <= n]
}
reducen <- function(n) {
  f <- function(x, y) c(x, seq(y, n))
  Reduce(f, 1:(n-1), c())
}
recursen <- function(n) {
  Recurse <- function(v) {
    if (length(v) > 2) c(v, Recall(tail(v, -1))) else v
  }
  Recurse(1:n)
}
0 голосов
/ 13 сентября 2018

Например,

> n <- 4
> X <- matrix(1:n, nrow = n, ncol = n)
> X
     [,1] [,2] [,3] [,4]
[1,]    1    1    1    1
[2,]    2    2    2    2
[3,]    3    3    3    3
[4,]    4    4    4    4
> lower.tri(X, diag = TRUE)
     [,1]  [,2]  [,3]  [,4]
[1,] TRUE FALSE FALSE FALSE
[2,] TRUE  TRUE FALSE FALSE
[3,] TRUE  TRUE  TRUE FALSE
[4,] TRUE  TRUE  TRUE  TRUE
> x <- X[lower.tri(X, diag = TRUE)]
> x
 [1] 1 2 3 4 2 3 4 3 4 4
> x[-length(x)]
[1] 1 2 3 4 2 3 4 3 4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...