read - Generar series 1,2,1,3,2,1,4,3,2,1,5,4,3,2,1.
python biopython (4)
Con sequence
:
rev(sequence(5:1))
# [1] 1 2 1 3 2 1 4 3 2 1 5 4 3 2 1
Estoy tratando de generar un vector que contenga una serie inversa creciente, como 1,2,1,3,2,1,4,3,2,1,5,4,3,2,1
.
Intenté usar un bucle para esto, pero no sé cómo apilar o concatenar los resultados.
for (i in 1:11)
{
x = rev(seq(i:1))
print(x)
}
[1] 1
[1] 2 1
[1] 3 2 1
[1] 4 3 2 1
[1] 5 4 3 2 1
[1] 6 5 4 3 2 1
[1] 7 6 5 4 3 2 1
[1] 8 7 6 5 4 3 2 1
[1] 9 8 7 6 5 4 3 2 1
[1] 10 9 8 7 6 5 4 3 2 1
[1] 11 10 9 8 7 6 5 4 3 2 1
También he estado experimentando con el rep
, rev
y seq
, que son mi opción favorita pero no llegaron muy lejos.
Otra alternativa es usar tail
dentro de lapply
, para seleccionar sucesivamente el número de elementos para mantener desde el vector inicial:
unlist(lapply(1:5, tail, x=5:1))
[1] 1 2 1 3 2 1 4 3 2 1 5 4 3 2 1
O, puede ser más rápido construir primero el vector base y luego invocarlo:
vec <- 5:1
unlist(lapply(rev(vec), tail, x=vec))
[1] 1 2 1 3 2 1 4 3 2 1 5 4 3 2 1
Podemos hacer esto con lapply
unlist(lapply(1:11, function(x) rev(seq(x))))
O como @ zx8754 mencionado en los comentarios, en lugar de rev(seq
,: puede usarse
unlist(lapply(1:11, function(x) x:1))
O como sugirió @BrodieG, podemos hacer esto más compacto eliminando la llamada de función anónima
unlist(lapply(1:11, ":", 1))
Y por diversión, usando matrices (e ignorando la advertencia;))
m <- matrix(c(1:5,0), ncol = 5, nrow = 5, byrow = T)
m[ upper.tri(m, diag = T) ]
# [1] 1 2 1 3 2 1 4 3 2 1 5 4 3 2 1
Y podemos simplificar el upper.tri
en sus componentes.
m[ row(m) <= col(m)]
# [1] 1 2 1 3 2 1 4 3 2 1 5 4 3 2 1
Y si puede manejar aún más la diversión, entonces, ¿qué hay de algunas evaluaciones comparativas:
library(microbenchmark)
maxValue <- 1000
vec2 <- maxValue:1
m2 <- matrix(c(1:maxValue,0), ncol = maxValue, nrow = maxValue, byrow = T)
microbenchmark(
henrik = {
rev(sequence(maxValue:1))
},
akrun = {
unlist(lapply(1:maxValue, function(x) x:1))
},
symbolix1 = {
m <- matrix(c(1:maxValue,0), ncol = maxValue, nrow = maxValue, byrow = T)
m[ row(m) <= col(m) ]
},
symbolix2 = {
m2[ row(m2) <= col(m2) ]
},
lmo1 = {
unlist(lapply(1:maxValue, tail, x=maxValue:1))
},
lmo2 = {
vec <- maxValue:1
unlist(lapply(rev(vec), tail, x=vec))
},
lmo3 = {
unlist(lapply(rev(vec2), tail, x=vec2))
}
)
# Unit: milliseconds
# expr min lq mean median uq max neval
# henrik 3.342175 4.095287 5.185095 4.960354 5.703463 32.08644 100
# akrun 1.535998 1.761439 2.159954 2.162721 2.292743 10.80862 100
# symbolix1 13.443495 15.145713 16.588118 17.145578 17.896521 20.81460 100
# symbolix2 8.640927 10.245634 11.656378 12.297788 12.791973 14.39691 100
# lmo1 13.124813 14.301375 17.253844 14.795471 15.718820 61.09737 100
# lmo2 13.026593 14.202633 18.042158 14.891164 17.729049 86.18921 100
# lmo3 13.355810 14.424353 18.497383 14.876103 20.100575 76.96622 100
En este ejemplo, akrun (y zx8754 por proxy) es el ganador!
Pero sé lo que estás pensando, ''¿por qué terminar toda la diversión allí?''
Bueno, escribamos nuestra propia función de C ++ y veamos cómo funciona
library(Rcpp)
cppFunction(''NumericVector reverseSequence(int maxValue, int vectorLength){
NumericVector out(vectorLength);
int counter = 0;
for(int i = 1; i <= maxValue; i++){
for(int j = i; j > 0; j--){
out[counter] = j;
counter++;
}
}
return out;
}'')
maxValue <- 5
reverseSequence(maxValue, sum(1:maxValue))
[1] 1 2 1 3 2 1 4 3 2 1 5 4 3 2 1
library(microbenchmark)
maxValue <- 1000
microbenchmark(
akrun = {
unlist(sapply(1:maxValue, function(x) x:1))
},
symbolix3 = {
reverseSequence(maxValue, sum(1:maxValue))
}
)
# Unit: microseconds
# expr min lq mean median uq max neval
# akrun 1522.250 1631.6030 3148.922 1829.9370 3357.493 45576.148 100
# symbolix3 338.626 495.3825 1293.720 950.6635 2169.656 3816.091 100