Matrix multiplication R - r

I just have an easy question: I have these two matrices
Matrix Y (264 rows and 4 columns)
[,1] [,2] [,3] [,4]
1751 -1.745529 0.3692280 0.04607022 -0.07004973
1752 -1.532722 0.5642921 0.07477571 0.03380135
1753 -1.657636 0.4660229 0.05772685 -0.03314599
1754 -1.685309 0.4540047 0.08254891 -0.01623810
1755 -1.702469 0.4483389 0.10709689 -0.03936556
1756 -1.761332 0.4505378 0.04801420 -0.06385137
Matrix E (4x4,of elements e)
[,1] [,2] [,3] [,4]
[1,] -0.8769976 -0.4706054 -0.07186508 0.06512449
[2,] -0.4085563 0.8198519 -0.40067903 -0.01951755
[3,] 0.2190770 -0.3206892 -0.86394973 -0.32055350
[4,] -0.1263415 0.0594299 0.29644997 -0.94478745
I want to do this for each year b(t)=∑(e[1,i]∙Y[,i]) with i from 1 to 4.
This is what I should get (a matrix 264x4),and this is the code I've used
betaNew1<-(Y[,1]%*%t(P[1,1]))
betaNew2<-(Y[,2]%*%t(P[1,2]))
betaNew3<-(Y[,3]%*%t(P[1,3]))
betaNew4<-(Y[,3]%*%t(P[1,4]))
beta_t<-data.frame(betaNew1,betaNew2,betaNew3,betaNew4)
betaNew1 betaNew2 betaNew3 betaNew4
1 1.530825 -0.1737607 -0.003310840 0.003000300
2 1.344193 -0.2655589 -0.005373763 0.004869730
3 1.453743 -0.2193129 -0.004148544 0.003759431
4 1.478012 -0.2136570 -0.005932384 0.005375955
5 1.493062 -0.2109907 -0.007696526 0.006974630
6 1.544684 -0.2120255 -0.003450544 0.003126900
How can I avoid to use 4 instructions?

We can try
res <- lapply(seq_len(nrow(P)), function(i) Y*P[i,][col(Y)])

Related

How might I raise all elements in the ith column of a matrix to the power of i?

I am currently trying to create an nxm matrix of accumulation factors based on a selection of n interest rates of m time periods. So, for example, the first row gives me the evolution of a single unit accumulating at an interest rate of r1, the second row the evolution at an interest rate of r2, and so on. This should give me a matrix that looks something like
1+r1 (1+r1)^2 (1+r1)^3 ...
1+r2 (1+r2)^2 (1+r2)^3 ...
1+r3 (1+r3)^2 (1+r3)^3 ...
.
.
.
To do this, I have created a matrix of the form
1+r1 1+r1 1+r1 ...
1+r2 1+r2 1+r2 ...
1+r3 1+r3 1+r3 ...
.
.
.
(with constant rows) and was hoping to raise every element in the ith row to the power of i (without using a loop). How might this be done?
One option is to loop over the sequence of columns, extract the matrix column and raise it to the power of the index
sapply(seq_len(ncol(m1)), function(i) (1 + m1[,i])^i)
# [,1] [,2] [,3] [,4] [,5]
#[1,] 2 49 1728 83521 5153632
#[2,] 3 64 2197 104976 6436343
#[3,] 4 81 2744 130321 7962624
#[4,] 5 100 3375 160000 9765625
#[5,] 6 121 4096 194481 11881376
Or without using a loop, make use of the col index which will return the same dimension as the original matrix and then do the power on the same dimension matrix
(m1 + 1)^col(m1)
# [,1] [,2] [,3] [,4] [,5]
#[1,] 2 49 1728 83521 5153632
#[2,] 3 64 2197 104976 6436343
#[3,] 4 81 2744 130321 7962624
#[4,] 5 100 3375 160000 9765625
#[5,] 6 121 4096 194481 11881376
Or another option is rep
(m1 + 1)^(rep(seq_len(ncol(m1)), each = nrow(m1)))
data
m1 <- matrix(1:25, 5, 5)

Is it possible to read only a sample of data using readRDS?

I have some big matrix saved using saveRDS:
# create same big matrix and save it
x = matrix(c(1:(10*10000)),10000,10)
saveRDS(x, 'test.RDS')
Now I would like to analyze only a sample on the data, but before taking the sample, I have been reading the full matrix:
# load big matrix and take a sample on the data after reading the data
x <- readRDS('test.RDS')
set.seed(1)
x[sample.int(dim(x)[1],5),]
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 2656 12656 22656 32656 42656 52656 62656 72656 82656 92656
[2,] 3721 13721 23721 33721 43721 53721 63721 73721 83721 93721
[3,] 5728 15728 25728 35728 45728 55728 65728 75728 85728 95728
[4,] 9080 19080 29080 39080 49080 59080 69080 79080 89080 99080
[5,] 2017 12017 22017 32017 42017 52017 62017 72017 82017 92017
I wonder whether it is possible to read only a sample on the data stored into an RDS file? That would mean not reading the whole matrix into memory before taking the sample, but somehow skip the data which does not belong to the sample?
I tried the following, and got the same result:
# find out the size of the matrix and load only the part of the matrix which is needed?
n <- dim(readRDS('test.RDS'))[1]
set.seed(1)
readRDS('test.RDS')[sample.int(dim(x)[1],5),]
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 2656 12656 22656 32656 42656 52656 62656 72656 82656 92656
[2,] 3721 13721 23721 33721 43721 53721 63721 73721 83721 93721
[3,] 5728 15728 25728 35728 45728 55728 65728 75728 85728 95728
[4,] 9080 19080 29080 39080 49080 59080 69080 79080 89080 99080
[5,] 2017 12017 22017 32017 42017 52017 62017 72017 82017 92017
How could I read a sample on RDS file without putting the full data temporarily into memory?
Alternatively, what kind of storing & loading functions one should use in order to be able to read only a sample from a file containing a matrix or data frame?

Calculate average of lowest values of matrix rows

I have a large matrix, e.g.
> mat = matrix(runif(100), ncol = 5)
> mat
[,1] [,2] [,3] [,4] [,5]
[1,] 0.264442954 0.6408534 0.76472904 0.2437074 0.08019882
[2,] 0.575443586 0.6428957 0.44188123 0.0230842 0.07502289
[3,] 0.894885901 0.5926238 0.55431966 0.7717503 0.52806173
[4,] 0.231978411 0.1192595 0.08170498 0.4264405 0.97486053
[5,] 0.344765840 0.5349323 0.85523617 0.2257759 0.20549035
[6,] 0.499130844 0.9882825 0.99417390 0.8070708 0.29963075
[7,] 0.613479990 0.8877605 0.34282782 0.9525512 0.91488004
[8,] 0.967166001 0.6115709 0.68169111 0.3067973 0.30094691
[9,] 0.957612804 0.5565989 0.88180650 0.3359184 0.17980137
[10,] 0.342177768 0.7735620 0.48154937 0.3692096 0.31299886
[11,] 0.871928110 0.3397143 0.57596030 0.4749349 0.47800019
[12,] 0.387563040 0.1656725 0.47796646 0.8956274 0.68345302
[13,] 0.628535870 0.3418692 0.86513964 0.8052477 0.01850535
[14,] 0.379472842 0.9176644 0.08829197 0.8548662 0.42151935
[15,] 0.071958980 0.6644800 0.90061596 0.4484674 0.32649345
[16,] 0.229463192 0.9995178 0.63995121 0.8369698 0.35091430
[17,] 0.291761976 0.5014815 0.35260028 0.6188047 0.68192891
[18,] 0.077610797 0.2747788 0.07084273 0.5977530 0.37134566
[19,] 0.675912490 0.6059304 0.29321852 0.5638336 0.73866322
[20,] 0.006010715 0.7697045 0.43627939 0.1723969 0.88665973
I want to extract the lowest and highest 2 values of each row and calculate their average.
Eventually, I'd like to generate a new matrix where the first column in the average of the lowest values, and the second column is the average of the highest values.
Thanks in advance!
I believe this does what you want:
do.call(rbind, apply(mat,1, function(x) {sorted = sort(x);
return(data.frame(min=mean(head(sorted,2)), max=mean(tail(sorted,2))))}))
Output:
min max
1 0.14333229 0.8877635
2 0.12311651 0.5283049
3 0.09367614 0.5433373
4 0.39926848 0.6361645
5 0.05196898 0.5473783
6 0.12876148 0.6153546
7 0.29893684 0.8436462
8 0.14254481 0.7023039
9 0.20889814 0.8863141
10 0.44838327 0.8641790
11 0.14859312 0.5533045
12 0.19728414 0.8619284
13 0.37049481 0.7448965
14 0.30070570 0.9320575
15 0.30333510 0.6774024
16 0.21908982 0.7077274
17 0.61804571 0.9239816
18 0.36525615 0.8531795
19 0.22751108 0.4993744
20 0.14251095 0.6353147
Hope this helps!

For Loop in R for snake draft?

I am fairly new to R, and am trying to automate a snake draft in R with a for loop. Essentially, I want to take a vector that has 9 columns (for each of the 9 teams) and take the first available player in that column (all 9 teams have a varying order of the same 36 players; ranked how each team captain feels the player will perform) and put it in a blank matrix that will ultimately have all the teams finalized.
As I have stated, there are 9 teams each drafting 4 players. Because it is a snake draft the "picking order" runs like this:
Team Captain 1 picks their first choice, then
Team Captain 2 picks their first choice (of the players left, Team Captain 1's first choice is no longer available), then
Team Captain 3 makes their first pick,
all the way to
Team Captain 9 who then takes their first pick AND their second pick, then
Team Captain 8 takes their second pick,
and this follows suit back to
Team Captain 1 who picks their second and third pick,
etc.
Because there are 9 Team Captains and 36 players to chose from, each team ultimately has four players (non-repeating). I hope I have explained this well enough. I love this site, and appreciate your help!
Here's a propose solution. Not the most elegant looking but should work for your problem:
players <- paste0("player", 1:36)
picks<-sample(players, 36)
draft <- matrix(NA, ncol=9, nrow=4)
for(i in 1:4){
if(i %in% c(1,3)) draft[i, 1:9] <- picks[(9*(i-1)+1):(9*(i-1)+ 9)]
if(i %in% c(2,4)) draft[i, ] <- rev(picks[(9*(i-1)+1):(9*(i-1)+ 9)])
}
draft
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
[1,] "player4" "player12" "player29" "player10" "player19" "player26" "player3" "player21" "player20"
[2,] "player17" "player7" "player9" "player5" "player6" "player23" "player15" "player35" "player13"
[3,] "player36" "player34" "player28" "player32" "player33" "player27" "player30" "player31" "player8"
[4,] "player11" "player22" "player2" "player18" "player24" "player25" "player16" "player1" "player14"
Here's a reasonably readable version:
set.seed(47)
players <- cbind(replicate(9, sample(1:36)), ID = 1:36) # column 10 is ID column
pick <- matrix(NA, 4, 9) # matrix to fill
for(round in 1:4){
direction <- if(round %% 2 == 1) {1:9} else {9:1}
for(team in direction){
pick[round, team] <- players[which.min(players[, team]), 'ID'] # store pick
players <- players[-which.min(players[, team]), , drop = FALSE] # erase player's row
}
}
pick # rows are rounds, columns are teams, numbers are player IDs
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
# [1,] 18 5 20 6 27 36 24 34 26
# [2,] 19 28 32 1 23 33 30 2 17
# [3,] 21 15 8 9 13 7 35 31 14
# [4,] 16 3 4 22 10 11 29 25 12

R image function

I have trouble understanding the image function in R. I have the following matrix
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 6.931799 7.092166 7.136029 6.735593 6.621951 6.740000 6.049774 6.162304 6.169014 5.626374
[2,] 7.942623 7.909091 9.923077 5.888889 8.647059 8.166667 6.625000 6.529412 7.571429 5.590643
[3,] 8.446237 6.800000 9.000000 9.631579 8.892857 7.083333 6.857143 6.250000 6.413793 5.491525
[4,] 7.698276 6.666667 8.833333 7.565217 9.100000 6.705882 6.421053 7.045455 6.045455 5.267857
[5,] 6.082524 8.300000 8.250000 8.777778 7.250000 7.928571 6.500000 6.920000 5.041667 4.970833
[6,] 6.128571 8.636364 7.300000 6.266667 7.500000 7.384615 6.727273 6.312500 5.638889 4.569231
[7,] 6.146739 7.000000 7.625000 6.615385 5.466667 5.941176 7.100000 6.687500 5.789474 4.479675
[8,] 5.403509 7.714286 6.500000 8.500000 6.384615 7.133333 6.294118 5.900000 5.615385 4.759804
[9,] 5.444444 5.666667 4.875000 6.200000 6.777778 6.166667 5.642857 6.222222 5.428571 4.385093
[10,] 5.186180 5.621118 5.004878 5.045016 4.875433 4.594340 4.260377 4.276382 4.205128 3.632721
and I would like to display it as an heatmap. To so so I use the image function as following
image(1:10,1:10,mat,axes=FALSE)
but the result is definitly not what is in my matrix!!]1
Any idea ?
thanks
Firstly, you should keep in mind that the matrix is printed from top left but plotted from bottom left, like Badger has said. Increasing the row index would move you to the right on the plot.
The color intensity increases from red to white.
Another thing that you might want to change is the range on your z value. The plot takes the min and max values from your matrix and sets that as the default range. However, you might want to add the following argument: zlim=c(0,10)
, so that your range is from 0 to 10?
Lastly, if you want your plot to correspond to the locations of your z values in the matrix, you could create a new matrix where you rotate your original matrix by 90 degrees clockwise:
t(apply(mat, 2, rev))

Resources