I have two vectors, base <- 1:10
, and power <- 1:10
; what I want is to use the for
loop to raise the power of each element of the base vector using the power vector.
i.e. c([1^1,1^2,...],[2^1, 2^2,...],[3^1,3^2,...]...)
I have tried nesting the for
loop, but since I'm super new to R, I have no clue how to get it working. My codes are:
for (i in 1:10) {
for (m in 1:10) {
rows <- i^m
}
}
CodePudding user response:
We can do this with outer
.
b <- 1:4; p <- 1:3
outer(b, p, `^`)
# [,1] [,2] [,3]
# [1,] 1 1 1
# [2,] 2 4 8
# [3,] 3 9 27
# [4,] 4 16 64
If a vector is needed, as.vector
outer(b, p, `^`) |> as.vector()
And a list
outer(b, p, `^`) |> as.data.frame() |> as.list()
# $V1
# [1] 1 2 3 4
#
# $V2
# [1] 1 4 9 16
#
# $V3
# [1] 1 8 27 64
A loop could look like this,
b <- 1:4; p <- 1:3
res <- array(dim=c(length(b), length(p)))
for (i in seq_along(b)) {
for (j in seq_along(p)) {
res[i, j] <- b[i]^p[j]
}
}
res
# [,1] [,2] [,3]
# [1,] 1 1 1
# [2,] 2 4 8
# [3,] 3 9 27
# [4,] 4 16 64
but it is very inefficient in R.
We could do it in Rcpp
, though.
Rcpp::sourceCpp(code='
#include <Rcpp.h>
using namespace Rcpp;
// [[Rcpp::export]]
NumericMatrix powv(NumericVector b, NumericVector p) {
int blen = b.size();
int plen = p.size();
NumericMatrix m(blen, plen);
for (int i = 0; i < blen; i ) {
for (int j = 0; j < plen; j ) {
m(i, j) = std::pow(b[i], p[j]);
}
}
return m;
}
')
powv(b, p)
# [,1] [,2] [,3]
# [1,] 1 1 1
# [2,] 2 4 8
# [3,] 3 9 27
# [4,] 4 16 64
Microbenchmark
b <- seq(0, 5, .01); p <- seq(0, 5, .01)
microbenchmark::microbenchmark(
outer=outer(b, p, `^`),
powv=powv(b, p),
Power_rui=Power(b, p),
`for`=forfun(b, p),
check='equal'
)
# Unit: milliseconds
# expr min lq mean median uq max neval
# outer 9.700440 9.922495 10.341630 9.981673 10.081983 13.71488 100
# powv 6.389418 6.418062 6.552114 6.434775 6.478917 8.35611 100
# Power_rui 11.074284 11.131459 11.433523 11.178858 11.267215 13.77799 100
# for 39.902641 40.970678 42.190528 42.313148 42.825829 47.53356 100
CodePudding user response:
Use sapply
, the ^
operator is vectorised either on the base or on the exponent (but not on both).
base <- 1:10
power <- 1:10
sapply(power, \(m) base^m)
#> [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#> [1,] 1 1 1 1 1 1 1 1 1 1
#> [2,] 2 4 8 16 32 64 128 256 512 1024
#> [3,] 3 9 27 81 243 729 2187 6561 19683 59049
#> [4,] 4 16 64 256 1024 4096 16384 65536 262144 1048576
#> [5,] 5 25 125 625 3125 15625 78125 390625 1953125 9765625
#> [6,] 6 36 216 1296 7776 46656 279936 1679616 10077696 60466176
#> [7,] 7 49 343 2401 16807 117649 823543 5764801 40353607 282475249
#> [8,] 8 64 512 4096 32768 262144 2097152 16777216 134217728 1073741824
#> [9,] 9 81 729 6561 59049 531441 4782969 43046721 387420489 3486784401
#> [10,] 10 100 1000 10000 100000 1000000 10000000 100000000 1000000000 10000000000
Created on 2022-09-24 with reprex v2.0.2
If a function is needed,
Power <- function(x, m) sapply(m, \(.m) x^.m)
Power(1:10, 1:10)
CodePudding user response:
If you have to use for
loops, you need to declare and initialize a storage object outside the loops. Something like this:
mat <- matrix(NA, 10, 10)
for (i in 1:10) {
for (m in 1:10) {
mat[i,m] <- i^m
}
}
mat
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 1 1 1 1 1 1 1 1 1 1
[2,] 2 4 8 16 32 64 128 256 512 1024
[3,] 3 9 27 81 243 729 2187 6561 19683 59049
[4,] 4 16 64 256 1024 4096 16384 65536 262144 1048576
[5,] 5 25 125 625 3125 15625 78125 390625 1953125 9765625
[6,] 6 36 216 1296 7776 46656 279936 1679616 10077696 60466176
[7,] 7 49 343 2401 16807 117649 823543 5764801 40353607 282475249
[8,] 8 64 512 4096 32768 262144 2097152 16777216 134217728 1073741824
[9,] 9 81 729 6561 59049 531441 4782969 43046721 387420489 3486784401
[10,] 10 100 1000 10000 100000 1000000 10000000 100000000 1000000000 10000000000
Note that for
and while
loops can usually be avoided in R and is done so preferably.