I’m currently attempting to solve an R brainteaser exercise about control flow and nested for loops.
I’m trying to calculate the mean of each column of a matrix without using built in functions.

Right now I’m stuck on how to reset the counter and the total variables that I use to find the average. Once I move on to the next column I have the values from the last column still in place. I tried using an IF statement to bring it back to 0 once it hit the column length using ncol, but that didn’t seem to work.

Here is what I have so far:

matrixMeans <- function(x)
{
# Computes the mean of each column of a matrix x.
total = 0
count = 0
toReturn = numeric(ncol(x))
for(ii in 1:ncol(x))
{
for(jj in 1:nrow(x)){
if(count > nrow(x)){
total = 0
count = 0
}
total = total + x[jj, ii]
print(x[jj, ii])
print(paste("total = ", total))
count = count + 1
print(paste("count = ", count))
avg = total/count
print(paste("avg = ", avg))
}
}
toReturn[ii] <- avg
return(toReturn)
}

If I feed this function the matrix:

[,1] [,2] [,3]
[1,] 1 4 7
[2,] 2 5 8
[3,] 3 6 9

It should return something like:

2, 5, 8

I’m pretty stuck right now, I’ve been looking at this code forever.

Hey @charlesd, this is a super interesting problem, thanks for sharing! Overall, you were on the right track. I basically took what you started, and moved things around a bit. Here’s the solution I came up with:

x <- matrix(1:9, nrow = 3, ncol = 3)
matrixMeans <- function(x)
{
# Computes the mean of each column of a matrix x.
toReturn = numeric(ncol(x))
for(ii in 1:ncol(x))
{
count = 0
total = 0
avg = 0
for(jj in 1:nrow(x)){
total = total + x[jj, ii]
count = count + 1
avg = total/count
}
print(paste("total = ", total))
print(paste("count = ", count))
print(paste("avg = ", avg))
toReturn[ii] <- avg
}
toReturn
}
matrixMeans(x)

Because we only want to print summaries for each column, we can bump the print statements out one level in the control structure. This way, we only print summaries for each column (e.g. for(ii in 1:ncol(x))).

Also, each time we iterate over a column, we want to append the new value for avg to the toReturn object, but we don’t want to print the output of toReturn until we’ve completed iterating through all of the columns in the matrix. So you can see in the code below that I bumped toReturn[ii] <- avg up so.

Finally, each time we’ve looped through each row in a column and appended the most recent value of avg to toReturn we’ll want to reset the following values to zero before we start iterating over the next column:

count = 0
total = 0
avg = 0

Let me know if you have any questions about this. Best,
-Casey

Thank you very much. I feel like saying I was close, but the truth is that I had moved around the count/total/avg statements many times and had given up on pursuing that as a solution. It seems I was barking up the wrong tree with my if statement.

So, just to reiterate what I’m seeing: the outside for loop ‘resets’ when it gets to a new column, so that’s the best place to reset the total/count/avg statements back to zero, while the inside for loop is the best place to increment those statements because they will run once every row.

I’m glad that there are built in functions/methods that can handle tasks like this, but I guess this did teach me about the application of nested for loops. I’m trying to think of times when I would use a nested for loop. Perhaps if I need to apply a function to every single value inside of a matrix?

Glad this was helpful. Your understanding sounds correct. Yes, nested for-loops can be useful when you are trying to apply to an operation to each row in a matrix or dataframe. This can be done to check if each individual element meets a condition, or to iteratively build/append a summary of some sort.

One thing I like about this exercise is that it challenges you to think about how to build a summary function that can be applied to matrices of different dimensions.