Combining different matrices in a for loop - r

I want to create different matrices in a loop and then combine (either cbind or rbind) them. But the following codes doesn't work. Why not? And how to fix it?
dependent = matrix(c(30,184,6,106), 2, 2, byrow=T)
independent = c(160,166)
expected = numeric()
{for(i in 1:length(independent))
a = dependent*independent[i]/sum(independent)
expected = cbind(expected,a)}
This gives:
expected
[,1] [,2]
[1,] 15.276074 93.69325
[2,] 3.055215 53.97546
This is the result of only using the final iteration of the for loop. So the result is like only 166 is used, but 160 isn't.

A few comments:
Your for loop brackets are in the wrong place. You have:
R> {for(i in 1:3)
+ cat(i, "\n")
+ cat(i, "\n")
+ }
1
2
3
3
instead you should have:
R> for(i in 1:3) {
+ cat(i, "\n")
+ cat(i, "\n")
+ }
1
1
2
2
3
3
When you construct a for loop and ommit the brackets, only the first line after the for statement is used.
You can make your for loop more efficient by saving the result of sum(independent) since that doesn't change with each iteration, i.e.
for(i in 1:length(independent)){
a = dependent*independent[i]
expected = cbind(expected,a)
}
expected = expected//sum(independent)
In fact you can vectorise the whole calculation
y = sapply(independent, '*', dependent)
matrix(y, ncol=4,nrow=2)/sum(independent)

You could forgo the for loop altogether and use:
X <- lapply(independent, function(x) (dependent*x)/sum(independent))
do.call("cbind", X)
EDIT: I edited my response as the order was not correct.

Related

Finding all combinations using recursion in R

I'm having issue with returning values from recursive functions, hoping you could help me out. I have a list with a bunch of matrices, each matrix representing a set of possible combinations and generated using combn(). As an example, this could be 3 matrices inside the list:
# set 1 has 4 elements, do nCk = 4C1:
set1 <- c("b2","b3","b4","b5")
set1 <- combn(set1,1,simplify = T)
# set 2 has 3 elements, choose 2:
set2 <- c("c1","c2","b2")
set2 <- combn(set2,2,simplify = T)
# set 3 has 10 elements, choose 1:
set3 <- combn(c(1:10),1, simplify = T)
If we were to print set2, for instance, it would have 2 rows (choose 2), and 3 columns (3C2 = 3):
> set2
[,1] [,2] [,3]
[1,] "c1" "c1" "c2"
[2,] "c2" "b2" "b2"
I need get all possible 4-element combinations (1 element per set above). I can do this using a while loop and simulating a state machine, but that solution is clunky and makes for long code. I know this can be done using recursion as I was able to print the 120 combinations correctly (code below), but when trying to return them or save them in a variable, either I get a <font color="red">subscript out of bounds error or the results repeat thousands of times. I want to avoid global variables too, this will be embedded in a rather large project, so I'd prefer to avoid bloating my workspace with more variables than needed.
Of course, when deployed the number of sets will be dynamic, and the elements per set will change too. The sets aren't too big either, so I would love to implement a recursive approach!
Working code to print:
combb <- function(allsets, number, carry){
if(number>length(allsets)){
print(carry)
return()
} else{
for(j in 1:length(allsets[[number]][1,])){
newcarry <- c(carry, allsets[[number]][,j])
number2 <- number + 1
combb(allsets, number2, newcarry)
}
}
}
Thank you!
I found that it was very hard to carry the results back and forth, as it required flags and lists or a different solution. What I did instead was create a wrapper function where I created a local variable. The recursive function is defined inside, and accesses ("globally") the variable mentioned above. Then, that variable is returned by the wrapper:
combb <- function(allsets){
carry <- integer(0)
height <- 0L
for (j in 1:length(allsets)) {
height <- height + length(allsets[[j]][, 1])
}
output <- matrix(allsets[[1]][0, 1], nrow = height, ncol = 0)
combb1 <- function(allsets, number, carry) {
if(number > length(allsets)){
output <<- cbind(output, carry, deparse.level = 0)
return()
} else{
for (j in 1:length(allsets[[number]][1,])) {
# Only add unique combinations (some combinations are vectors)
if((TRUE %in% (allsets[[number]][, j] %in% carry)) == FALSE) {
newcarry <- c(carry, allsets[[number]][, j], use.names = FALSE)
number2 <- number + 1
combb1(allsets, number2, newcarry)
} else{
next()
}
}
}
}
combb1(allsets, 1, carry)
return(output)
}
As you can see from that solution, recursion is neat (combb1 function) and doesn't clutter any of the global/workspace variables.

Save loop results as csv table

I have simple loop that generate a value at each step, and I want to save all results as a single table. Problem is that each step overwrites the previous.
for(i in 1:5){
x = 3*i
print(c(i,x))
}
This gives
[1] 1 3
[1] 2 6
[1] 3 9
[1] 4 12
[1] 5 15
Now I create a matrix that I will then save as a csv file, but it only shows the final step of the loop.
results = matrix(c(i,x), ncol = 2)
[,1] [,2]
[1,] 5 15
write.table(results, file = "Results.csv", col.names=NA, append = T)
How to show the entire list of results? Thanks in advance!
(ps.- I know that a similar question has been posted previously, e.g. Write output of R loop to file, but the problem was quite specific and I did not manage to adapt the answers to my case).
Your loop only prints, to the console, the results. The matrix you're creating only relies on the single (and last) value of i. There are many ways to do it but if you really want to write a matrix, then you need to store them somewhere to export all iteration intermediate results. You can try something like:
results <- matrix(NA, nrow=5, ncol=2)
for(i in 1:5){
results[i, ] <- c(i, 3*i)
}
write.table(results, file = "Results.csv", col.names=NA, append = T)
And by the way you don't really need a loop here:
i <- 1:5
m <- matrix(c(i, 3*i), nrow=5)
would do the job.
You can usually use sapply instead of for-loops:
results <- t(sapply(1:5, function(x) c(x, 3*x)))
write.table(results, file="Results.csv", col.names=NA, append=T)
Assuming you really want/need a for-loop
1) You store all the result into a matrix and then you write the whole matrix to file
n = 5;
results = matrix(NA, ncol=2, nrow=n);
for(i in 1:n) {
results[i, ] = c(i, x);
}
write.table(results, file = "Results.csv", col.names=NA, append = T);
This is a "good" solution if you don't have many results and you want to access the file just once.
2) You store current result only into a matrix and you write to file at each iteration
n = 5;
for(i in 1:n) {
results = matrix(c(i,x), ncol = 2)
write.table(results, file = "Results.csv", col.names=NA, append = T);
}
This is a "good" solution if you have many data and memory limits. Maybe slower than the previous one because you will open the file many times...
To append using a matrix you could use:
exampleMatrix <- matrix(ncol = 2)
for(i in 1:5){
x = 3*i
if(i ==1){
exampleMatrix<- rbind(c(x,i))
}else{
exampleMatrix<- rbind(exampleMatrix,c(x,i))
}}
To append to a dataframe using a loop you could use the following:
exampleDF <- data.frame()
for(i in 1:5){
x = 3*i
exampleDF <- rbind(exampleDF,c(x,i))
}
write.csv(exampleDF, "C:\\path")
So when you want to store you values while using a loop, it's important to index. Below, I created some code where a(the iteration) and x(the value x * 3) are each stored inside a vector.
After the loop has finished, I combine the two vectors into one data frame with the cbind() function
a <- vector()
x <- vector()
for(i in 1:5){
a[i] = i
x[i] = 3*i
}
df <- as.data.frame(cbind(a, x))
There are other ways to do this without loops. Once you start raising the number of iterations, or doing nested loops, the processing time starts to get really high. Other options are in the apply package.
Hope this helped!

Change value in matrix using defined function in R

I am still new to R.
I was wondering how to use self-defined function to change elements in matrix.
Say, I have a matrix "test"test = matrix(c(1:9), 3, 3)
and I wrote a function "testFunction" to add each element by 20.
testFunction = function(){
for(i in rownames(test)){
for(j in colnames(test)){
test[i,j] = test[i,j] + 20
}
}
}
If I do it manually, such as test[1,1] = test[1,1] + 20, it works.
But if I use the function I wrote, the matrix remain the same.
The "test" matrix after running the "testFunction" is still
[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9
Does anyone know why? And how can I change the values in the matrix using functions?
Thanks.
Update
So, actually I am creating a 452*452 matrix "pairMatrix" and a function "countPair"
pairMatrix = matrix(0, 452,452)
rownames(pairMatrix) = players
colnames(pairMatrix) = players
and
I will pass a data frame to the function, and the function will loop through each row to find "Player1" and "Player2". Then, using these two values as row name and column name to find the element in the pairMatrix and add by 1.
countPair = function(someDataFrame, pairMatrix){
for (i in rownames(someDataFrame)){
w = someDataFrame[i,"Player1"]
l = someDataFrame[i,"Player2"]
pairMatrix[w,l] = pairMatrix[w,l] + 1
pairMatrix[l,w] = pairMatrix[l,w] + 1
}
return(pairMatrix)
}
However, though the simple test case now works by following the suggestion, this complicated case does not work.
Any suggestion?
Thanks.
If you want to add 20 to your matrix, you only need:
test <- test + 20
However, assuming that you need to make this function for another purpose; the problem is due to two reasons:
colnames and rownames are NULL for matrices, so your function is not iterating.
In your function you have to return the output of your function.
Then, the following code will work:
test <- matrix(c(1:9), 3, 3)
testFunction <- function(){
for(i in 1:dim(test)[1]){
for(j in 1:dim(test)[2]){
test[i,j] <- test[i,j] + 20
}
}
return(test)
}
test <- testFunction()
Although the previous code work, it is still not good because the idea of a function is to take an input, process it and return and output. The following code makes that:
test <- matrix(c(1:9), 3, 3)
testFunction = function(input){
for(i in 1:dim(input)[1]){
for(j in 1:dim(input)[2]){
input[i,j] <- input[i,j] + 20
}
}
return(input)
}
test_added <- testFunction(test)

How to change final result of loop as a data frame

x1=c(55,60,75,80)
x2=c(30,20,15,23)
x3=c(4,3,2,6)
x=data.frame(x1,x2,x3)
From this function :
NAins=function(x,alpha=0.3){
x.n=NULL
for (i in 1:ncol(x)){
S= sort(x[,i], decreasing=TRUE)
N= S[ceiling(alpha*nrow(x))]
x.n= ifelse(x[,i]>N, NA, x[,i])
print(x.n) }
}
How to save the final result as adataframe look like the original dataset ?however I used data.frame(x.nmar) .
and How to get the result out of the loop ?.
Better to use lapply here to avoid side effect of the for-loop:
NAins <- function(x,alpha=0.3){
Nr <- nrow(x)
lapply(x,function(col){
S <- sort(col, decreasing=TRUE)
N <- S[ceiling(alpha*Nr)]
ifelse(col>N, NA, col)
})
Then you can coerce the result to a data.frame:
as.data.frame(NAins(dx))
Converting the comment to answer
If you want to achieve this the loop way, you will need to predefine a matrix or a data frame and then fill it up (In your case you can just use your original x data.frame because the function will not update the original data set in the global environment). After the loop ends, you will need to return it because all the variables you've created within the function will be removed. print isn't being saved anywhere neither. Also, running ceiling(alpha*nrow(x)) in a loop doesn't make sense as it always stays the same. Neither the ifelse is needed if you only have a single alternative each time. See below
NAins=function(x, alpha = 0.3){
N <- ceiling(alpha * nrow(x)) ## Run this only once (take out of the loop)
for(i in 1:ncol(x)){
S <- sort(x[, i], decreasing = TRUE)
x[x[, i] > S[N], i] <- NA # don't use `ifelse`, you only inserting one value
}
x # return the result after the loop ends
}
Test
NAins(x)
# x1 x2 x3
# 1 55 NA 4
# 2 60 20 3
# 3 75 15 2
# 4 NA 23 NA

Store values in For Loop

I have a for loop in R in which I want to store the result of each calculation (for all the values looped through). In the for loop a function is called and the output is stored in a variable r in the moment. However, this is overwritten in each successive loop. How could I store the result of each loop through the function and access it afterwards?
Thanks,
example
for (par1 in 1:n) {
var<-function(par1,par2)
c(var,par1)->var2
print(var2)
So print returns every instance of var2 but in var2 only the value for the last n is saved..is there any way to get an array of the data or something?
initialise an empty object and then assign the value by indexing
a <- 0
for (i in 1:10) {
a[i] <- mean(rnorm(50))
}
print(a)
EDIT:
To include an example with two output variables, in the most basic case, create an empty matrix with the number of columns corresponding to your output parameters and the number of rows matching the number of iterations. Then save the output in the matrix, by indexing the row position in your for loop:
n <- 10
mat <- matrix(ncol=2, nrow=n)
for (i in 1:n) {
var1 <- function_one(i,par1)
var2 <- function_two(i,par2)
mat[i,] <- c(var1,var2)
}
print(mat)
The iteration number i corresponds to the row number in the mat object. So there is no need to explicitly keep track of it.
However, this is just to illustrate the basics. Once you understand the above, it is more efficient to use the elegant solution given by #eddi, especially if you are handling many output variables.
To get a list of results:
n = 3
lapply(1:n, function(par1) {
# your function and whatnot, e.g.
par1*par1
})
Or sapply if you want a vector instead.
A bit more complicated example:
n = 3
some_fn = function(x, y) { x + y }
par2 = 4
lapply(1:n, function(par1) {
var = some_fn(par1, par2)
return(c(var, par1)) # don't have to type return, but I chose to make it explicit here
})
#[[1]]
#[1] 5 1
#
#[[2]]
#[1] 6 2
#
#[[3]]
#[1] 7 3

Resources