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)
Related
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.
I'm trying to apply a function to a matrix inside a for loop. The output should also be a matrix that changes at each step of the loop. The codes below explains my problem:
I1=apply(I0, 1, func1)
I2=apply(I1, 1, func1)
I3=apply(I2, 1, func1)
.
.
I10=apply(I9, 1, func1)
I0,I1,...I10 are each 4X10 matrix, func 1 is a predefined function. I've been attempting to solve this problem with a loop. I can't find much information on this. I need something like this:
for(i in 1:10){
I[i]=apply(I[i-1],1,func1)
}
There are two easy ways to go for:
1- Using get and assign:
# How get and assign work:
x0 = 10
get(paste0("x", 0)) # get the variable passed as a string argument - returns 10
assign(paste0("x", 0), 20) # assign 20 to x
print(x0) #20
# And.. the recursion
x0 = 2 # recursive initialization
for(i in 1:5) {
previousValue = get(paste0("x", i-1))
thisValue = previousValue * 2
assign(paste0("x", i), thisValue)
}
.
.
2- Using the magic of a list:
x0 = 2 # recursive initialization
myResults = list(x0)
# Now, the recursion!
for(i in 1:5) {
thisValue = myResults[[i]]
nextValue = c(thisValue * 2) # Some random calculation, use your function instead
myResults[[i+1]] = nextValue # Now add to the list
}
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
I'm trying to calculate the number of pairwise differences between a long list of sequences, and put it back into a matrix form. This is a toy example of what I want to do.
library(MiscPsycho)
b <- c("-BC", "ACB", "---") # Toy example of sequences
workb <- expand.grid(b,b)
new <- c(1:9)
# Need to get rid of this for loop somehow
for (i in 1:9) {
new[i] <- stringMatch(workb[i,1], workb[i,2], normalize="NO")
}
workb <- cbind(workb, new)
newmat <- reShape(workb$new, id=workb$Var1, colvar=workb$Var2)
a <- c("Subject1", "Subject2", "Subject3") #Relating it back to the subject ID
colnames(newmat) <- a
rownames(newmat) <- a
newmat
I'm not very familiar with using the apply functions, but I'd like to use it to be able to replace the for loop, which will probably get slow considering I have a large number of sequences. (The stringMatch function is from MiscPsycho). Please let me know how to make it more efficient!
Thank you very much!
To get those "pairwise distances" I would have done something like:
Vm <- Vectorize(stringMatch)
nex <- outer(b,b, FUN=Vm, normalize = "NO")
nex
[,1] [,2] [,3]
[1,] 0 3 2
[2,] 3 0 3
[3,] 2 3 0
To replace the loop
new <- apply(workb, 1, function(x) stringMatch(x[[1]],x[[2]], normalize="NO"))
I would make a function that takes your index, i, and returns new[i].
myfun <- function(i) {
stringMatch(workb[i, 1], workb[i, 2], normalize='NO')
}
Then you can apply along your new vector:
workb$new <- unlist(lapply(new, myfun))
In general, you are using a for loop correctly in R. You have allocated the vector new before hand and are filling it rather than growing it.
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.