R: Split one matrix into many matrices - r

How can I split a matrix into many submatrixes? Every submatrix should contain a selection of rows of the initial matrix.
The initial matrix is imported out of an .csv-file:
seri <- read.table("/PATH/seriation_testdaten.csv", sep="\t", head=TRUE, row.names=1)
This matrix seri contains numeric values like for example a matrix like seritest:
seritest <- matrix(1:100,10)
Now I would like to divide the rows of this matrix into groups. For example, I would like to have groups each with three rows. So one group should contain the rows 1,2 and 3, the next one the rows 4,5 and 6 and so on, until nrow(seri) is reached. It's no problem, if the last group just contains less than three rows.
Matrix 1:
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 1 11 21 31 41 51 61 71 81 91
[2,] 2 12 22 32 42 52 62 72 82 92
[3,] 3 13 23 33 43 53 63 73 83 93
Matrix 2:
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[4,] 4 14 24 34 44 54 64 74 84 94
[5,] 5 15 25 35 45 55 65 75 85 95
[6,] 6 16 26 36 46 56 66 76 86 96
Matrix 3:
...
That's the first step. But I would like to go further. In this example I have groups of three rows in the resulting submatrices. But I also want the resulting submatrices for groups of 1 row, 2 rows, 4 rows, 5 rows and so on up to nrow(seri) rows. So basically hundreds of submatrices which are each part of a unit based on the decision how big the group-size should be.
Thanks to the help of #farnsy I was able to produce working code, which does exactly what I want:
seritest <- matrix(1:10000,100)
a = nrow(seritest)
e = 1:nrow(seritest)
seri_sub <- list()
U=1
while(U<=a) {
Q=0
AQ=0
EQ=0
Uk <- U*1000;
repeat{
(e[U]*Q)+1 -> EQ;
Q=Q+1;
e[U]*Q -> AQ;
if(AQ>a) break
seri_sub[[Uk+Q]] <- seritest[EQ:AQ,];
};
U=U+1;
}
I can access the matrices by calling for example seri_sub[[3002]]. Like this I get the second (300**2**) group (rows 4,5 and 6) of the unit which is the result of a division of the initial matrix into groups of three (**3**002).
Like already mentioned by #Dason, this code is inefficient. Many list-elements are empty (NULL). Maybe somebody has an idea how to improve it.
This code runs without any further packages. R version 3.0.2 (2013-09-25). OS: Ubuntu 14.04 (64bit).
(I'm not a native speaker - please excuse the lack of eloquence)

seri doesn't seem like a list here. Neither do A or B, actually. Are you sure you are talking about lists at all? It looks more like you want to subset a matrix a bunch of times, creating submatrices. I can't imagine you actually want "random" names, either. That's crazy talk.
If you want to break up a matrix, why not store all the resulting matrices in an actual list?
myList <- list()
myList[[1]] <- seri[a:b,]
myList[[2]] <- seri[c:d,]
You can see how it would be pretty easy to put this in a loop. Now myList is a list of matrices and, for example, mylist[[i]] would be the i-th matrix. If you want the second row and third column entry, it would be mylist[[i]][2,3].

Related

Single for loop [duplicate]

This question already has answers here:
Multiplying vector combinations
(2 answers)
Closed 5 years ago.
I would like to create a single for-loop instead of using a nested for this question.
Required: fill up Matrix (foo) with multiples of loopvec1 and loopvec2 using a single for loop.
So far, I am only able to solve it using nested for loops. Here are my codes:
loopvec1 <- 5:7
loopvec2 <- 9:6
foo <- matrix(NA, length(loopvec1), length(loopvec2))
for (i in 1:length(loopvec1)) {
for (j in 1:length(loopvec2)) {
foo[i, j] <- loopvec1[i] * loopvec2[j]
}
}
foo
Output (foo):
[,1] [,2] [,3] [,4]
[1,] 45 40 35 30
[2,] 54 48 42 36
[3,] 63 56 49 42
May I know how do I achieve the same results just by using a single for loop instead?
Edit: I am aware that there is another function "outer" that produces the same result (which resulted in this question being marked as a duplicate), however, the question that I am stuck with requires me to use a single for loop instead of any other functions.
try this:
loopvec1 <- 5:7
loopvec2 <- 9:6
foo <- matrix(NA, length(loopvec1), length(loopvec2))
for (i in 1:length(loopvec1)) {
foo[i,] <- loopvec1[i] * loopvec2
}
foo
results:
> foo
[,1] [,2] [,3] [,4]
[1,] 45 40 35 30
[2,] 54 48 42 36
[3,] 63 56 49 42

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

Extract minima returns

I am trying to apply the block maxima (in my case minima) approach of Extreme Value Theory to financial returns. I have daily returns for 30 financial indices stored in a csv file called 'Returns'. I start by loading the data
Returns<-read.csv("Returns.csv", header=TRUE)
I then extract the minimum returns over consecutive non-overlapping blocks of equal length (i.e., 5 days) for each index I have in my 'Returns.csv' file. For that, I do the following
for (xx in Returns) #Obtain the minima.
{
rows<-length(xx) #This is the number of returns
m<-5 #When m<-5 we obtain weekly minima. Change accordingly (e.g., 20)
k<-rows/m #This is the number of blocks (i.e., number of returns/size of block),
bm<-rep(0,k) #which is also the number of extremes
for(i in 1:k){bm[i]<-min(xx[((i-1)*m+1):(i*m)])}
#Store the minima in a file 'minima.csv'
write.table(bm,file="minima.csv", append=TRUE, row.names=FALSE, col.names=FALSE)
The code extracts the minima returns for all indices correctly but when the minima are stored in the file 'minima.csv' they all appear in the same column (appended).
What I want the code to do is to read the financial returns contained in the first column of the file 'Returns.csv', extract the minima returns over consecutive non-overlapping blocks of equal length (i.e., 5 days) and store them in the first column of the file 'minima.csv'. Then do exactly the same for the financial returns contained in the second column of the file 'Returns.csv' and store the minima returns in the second column of the file 'minima.csv', and so on, until I reach column 30.
I think your data looks similar to this:
> m <- matrix(1:40, ncol=4)
> m
[,1] [,2] [,3] [,4]
[1,] 1 11 21 31
[2,] 2 12 22 32
[3,] 3 13 23 33
[4,] 4 14 24 34
[5,] 5 15 25 35
[6,] 6 16 26 36
[7,] 7 17 27 37
[8,] 8 18 28 38
[9,] 9 19 29 39
[10,] 10 20 30 40
Obviously you have more rows and columns and your data is not just the sequence of 1 to 40. To chunk each column with a size of 5 and find the minimum for each column run:
> apply(m, 2, function(x) sapply(split(x, ceiling(seq_along(x)/5)), min))
[,1] [,2] [,3] [,4]
1 1 11 21 31
2 6 16 26 36
Basically the apply is splitting m by the columns and applying the function to each column. The inner function takes each column, chunks the columns and then returns the minimum of each chunk. Your data is in a dataframe not a matrix so you need to do this before you run the command above.
m <- as.matrix(Returns)
To write this to a csv
> mins <- apply(m, 2, function(x) sapply(split(x, ceiling(seq_along(x)/5)), min))
> write.table(mins, file="test.min.csv", sep=',', row.names=F, col.names=F, quote=F)

Random Vectors Regardless of Order

What I am looking to do is generate n vectors of length k such that each value in the vector is a random number, and that there are no repeated vectors regardless of order of the integers in each vector. For example, there would not be both the vectors 1,2,3 and 2,1,3.
So far what I have is the following to generate one vector, and I was planning on looping through this code to generate the n vectors.
vector<- sample(1:20000,k)
One idea that I had would be to sort all vectors in ascending order and then remove duplicate vectors. Is there an easier/more efficient way?
Thanks!
One approach would be to generate all the possible combinations, then choose from that set. This would guarantee no duplicates:
> tmp <- combn(100, 3)
> dim(tmp)
[1] 3 161700
> tmp[ , sample( ncol(tmp), 10 ) ]
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,] 34 35 28 3 3 29 8 24 50 53
[2,] 54 54 63 57 17 86 31 30 52 81
[3,] 97 79 87 92 53 94 90 83 87 97
Of course this will only work if the total number of combinations can fit in memory. Though there are ways to iterate through the combinations and only keep some, or to generate a sample of integers, then convert them to the appropriate combination.
If the number of samples you want is small relative to the number of possible combinations then the rejection method will probably be more efficient. But this could work better if the number of samples is large relative to the number of combinations which would lead to a large number of duplicates.

Perform 'cross product' of two vectors, but with addition

I am trying to use R to perform an operation (ideally with similarly displayed output) such as
> x<-1:6
> y<-1:6
> x%o%y
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 2 3 4 5 6
[2,] 2 4 6 8 10 12
[3,] 3 6 9 12 15 18
[4,] 4 8 12 16 20 24
[5,] 5 10 15 20 25 30
[6,] 6 12 18 24 30 36
where each entry is found through addition not multiplication.
I would also be interested in creating the 36 ordered pairs (1,1) , (1,2), etc...
Furthermore, I want to use another vector like
z<-1:4
to create all the ordered triplets possible between x, y, and z.
I am using R to look into likelihoods of possible total when rolling dice with varied numbers of sizes.
Thank you for all your help! This site has been a big help to me. I appreciate anyone that takes the time to answer a stranger's question.
UPDATE So I found that `outer(x,y,'+') will do what I wanted first. But I still don't know how to create ordered pairs or ordered triplets.
Your first question is easily handled by outer:
outer(1:6,1:6,"+")
For the others, I suggest you try expand.grid, although there are specialized combination and permutation functions out there as well if you do a little searching.
expand.grid can answer your second question:
expand.grid(1:6,1:6)
expand.grid(1:6,1:6,1:4)

Resources