I am struggling with a loop in R where I have to use dynamic variable names (which I am told is a bad idea from the other posts about dynamic variable names, but I am pretty sure that I need to based on my file structure). Each folder for which the loop enters, there is a different number of files.
The dynamic variable names contain matrices and I need to look in each row/column of the matrix and output a new matrix.
Streamlined example:
var 1 is a matrix(0,40,40)
var 2 is a matrix(0,45,45)
var 3 is a matrix(0,40,40)
For (f in 1:(length of var3s)) # the number of files in the folder, in each folder:
For (g in 1: ncol(var1)) {
For (h in 1: nrow(var1)) {
if (var 1[g,h]>4 & var 2[g,h]<1)
{ var3[f] [g,h]<-1} # <- you cannot do this, but this is ultimately what I want
}
}
I want to take the f-th variable matrix from variable 3's list and assign a value to the location at [g,h]
I've done this before with real variable names, but I am struggling with adding the dynamic element. This is what it looks like and the errors I'm getting.
for (f in 1:(length(LD139_040))){
assign(paste0("LD139_040s",f),
matrix(0,nrow(eval(parse(text=paste0("B139_040",f)))),
ncol(eval(parse(text=paste0("B139_040",f)))))) # this effectively creates my new matrix (var3 above) the size I need based on the files above
for (g in 1:(ncol(eval(parse(text=paste0("B139_040",f)))))){
for (h in 1:(nrow(eval(parse(text=paste0("B139_040",f)))))){
if (S139_040[g,h]>10 &
(assign(paste0("LD139_040",f), as.matrix(raster(LD139_040[f]))))[g,h]>.295 &
(assign(paste0("LD139_040",f), as.matrix(raster(LD139_040[f]))))[g,h]<.33 &
(assign(paste0("B139_040",f), as.matrix(raster(Blue139_040[f]))))[g,h]<180)
# this section also works and will give me a t/f at each location [g,h]
# if true, assign the value 1 to the new matrix LD139_040 at f
{assign(paste0("LD139_040s", f)[g,h], 1)}
}
}
}
I have tried a variety of combinations of eval and assign to organize the last statement, and I get errors such as 'invalid first assignment', incorrect number of dimensions, and target of assignment expands to non-language object.
Thanks for your help!
R version 3.1.1 "Sock it to Me" with library(raster)
This did not require dynamic variable names. At each iteration within the loop the all of the names will change at the same time.
For example, this is how I answered the section in code block 2:
for (f in 1:(length(LD139_040))){
currenttile<-LD139_040[f]
Blue<-B139_040[f]
newmatrix<- matrix(0,nrow(Blue),ncol(Blue))
for (g in 1:(ncol(B139_040[f]))){
for (h in 1:(nrow(B139_040[f]{
if (S139_040[g,h]>10 & currenttile[g,h]>.295 & currenttile[g,h]<.33 & Blue [g,h]<180)
{newmatrix[g,h]<-1}
}
}
}
Put even more simply, since I learned that as long as the matrices are the same dimensions, you do not have to loop through each location:
for (f in 1:(length(LD139_040))){
currenttile<-LD139_040[f]
Blue<-B139_040[f]
newmatrix<- matrix(0,nrow(Blue),ncol(Blue))
currenttile[currenttile >.295 & currenttile <.33]<- 1
Blue[Blue<180]<- 1
newmatrix[Blue==1 & currenttile==1]<- 1
}
So thanks to everyone who tried to decipher this, it was a confusing problem for me to it took a while to figure out how to best approach it, (and obviously how to explain it). I hope this helps someone!
Related
Suppose we have given dataframe in R. By 0--7, it means it is taking integer values from 0-7 i.e. 0,1,2,3,4,5,6,7.
I am interested in making a function such that
If a[1,1]>alpha, it goes and checks its children i.e. 0--7 consists of a[1,2] and a[2,2].
So,
{a[2,1]>alpha
{a[4,1]>alpha
{a[5,1]>alpha
ps=list.append(0)
else ps=list.append(1)
}}}
Here, alpha is a a threshold. The ps is appended from values of 0 to 15 based on this criteria.
My code is
{for (i in 1:2)
{ if (a[j,i]>alpha)
{if (i%%2==1}
{j=j*2
if (a[j,i]>alpha
###here i want to go recursively i think and where and how should i add append values to the list
if a[j,i+1]>alpha}
if{i%%2==0}
{}
}}
I am stuck and confused at the same time. Any help or advices would be greatly appreciated.
Thanks
I am trying to change a variable in a function but even tho the function is producing the right values, when I go to use them in the next sections, R is still using the initial values.
I created a function to update my variables NetN and NetC:
Reproduction=function(NetN,NetC,cnrep=20){
if(NetC/NetN<=cnrep) {
DeltaC=NetC*p;
DeltaN=DeltaC/cnrep;
Crep=Crep+DeltaC;
Nrep=Nrep+DeltaN;
Brep=(Nrep*14+Crep*12)*2/1e6;
NetN=NetN-DeltaN; #/* Update N, C values */
NetC=NetC*(1-p)
print ("'Using C to allocate'")
}
else {
print("Using N to allocate");
DeltaN=NetN*p;
DeltaC=DeltaN*cnrep;
Nrep=Nrep+DeltaN;
Crep=Crep+DeltaC;
Brep=(Nrep*14+Crep*12)*2/1e6;
NetN=NetN*(1-p);
NetC=NetC-DeltaC;
} } return(c(NetC=NetC,NetN=NetN,NewB=NewB,Crep=Crep,Nrep=Nrep,Brep=Brep))}
When I use my function by say doing:
Reproduction(NetN=1.07149,NetC=0.0922349,cnrep=20)
I get the desired result printed out which includes:
NetC=7.378792e-02
However, when I go to use NetC in the next section of my code, R is still using NetC=0.0922349.
Can I make R update NetC without having to define a new variable?
In R, in general, functions shouldn't change things outside of the function. It's possible to do so using <<- or assign(), but this generally makes your function inflexible and very surprising.
Instead, functions should return values (which yours does nicely), and if you want to keep those values, you explicitly use <- or = to assign them to objects outside of the function. They way your function is built now, you can do that like this:
updates = Reproduction(NetN = 1.07149, NetC = 0.0922349, cnrep = 20)
NetC = updates["NetC"]
This way, you (a) still have all the other results of the function stored in updates, (b) if you wanted to run Reproduction() with a different set of inputs and compare the results, you can do that. (If NetC updated automatically, you could never see two different values), (c) You can potentially change variable names and still use the same function, (d) You can run the function to experiment/see what happens without saving/updating the values.
If you generally want to keep NetN, NetC, and cnrep in sync, I would recommend keeping them together in a named vector or list, and rewriting your function to take that list as input and return that list as output. Something like this:
params = list(NetN = 1.07149, NetC = 0.0922349, cnrep = 20)
Reproduction=function(param_list){
NetN = param_list$NetN
NetC = param_list$NetC
cnrep = param_list$cnrep
if(NetC/NetN <= cnrep) {
DeltaC=NetC*p;
DeltaN=DeltaC/cnrep;
Crep=Crep+DeltaC;
Nrep=Nrep+DeltaN;
Brep=(Nrep*14+Crep*12)*2/1e6;
NetN=NetN-DeltaN; #/* Update N, C values */
NetC=NetC*(1-p)
print ("'Using C to allocate'")
}
else {
print("Using N to allocate");
DeltaN=NetN*p;
DeltaC=DeltaN*cnrep;
Nrep=Nrep+DeltaN;
Crep=Crep+DeltaC;
Brep=(Nrep*14+Crep*12)*2/1e6;
NetN=NetN*(1-p);
NetC=NetC-DeltaC;
}
## Removed extra } and ) ??
return(list(NetC=NetC, NetN=NetN, NewB=NewB, Crep=Crep, Nrep=Nrep, Brep=Brep))
}
This way, you can use the single line params <- Reproduction(params) to update everything in your list. You can access individual items in the list with either params$Netc or params[["NetC"]].
i tried updating data in dataframe but its unable to get updating
//Initialize data and dataframe here
user_data=read.csv("train_5.csv")
baskets.df=data.frame(Sequence=character(),
Challenge=character(),
countno=integer(),
stringsAsFactors=FALSE)
/Updating data in dataframe here
for(i in 1:length((user_data)))
{
for(j in i:length(user_data))
{
if(user_data$challenge_sequence[i]==user_data$challenge_sequence[j]&&user_data$challenge[i]==user_data$challenge[j])
{
writedata(user_data$challenge_sequence[i],user_data$challenge[i])
}
}
}
writedata=function( seqnn,challng)
{
#print(seqnn)
#print(challng)
newRow <- data.frame(Sequence=seqnn,Challenge=challng,countno=1)
baskets.df=rbind(baskets.df,newRow)
}
//view data here
View(baskets.df)
I've modified your code to what I believe will work. You haven't provided sample data, so I can't verify that it works the way you want. I'm basing my attempt here on a couple of common novice mistakes that I'll do my best to explain.
Your writedata function was written to be a little loose with it's scope. When you create a new function, what happens in the function technically happens in its own environment. That is, it tries to look for things defined within the function, and then any new objects it creates are created only within that environment. R also has this neat (and sometimes tricky) feature where, if it can't find an object in an environment, it will try to look up to the parent environment.
The impact this has on your writedata function is that when R looks for baskets.df in the function and can't find it, R then turns to the Global Environment, finds baskets.df there, and then uses it in rbind. However, the result of rbind gets saved to a baskets.df in the function environment, and does not update the object of the same name in the global environment.
To address this, I added an argument to writedata that is simply named data. We can then use this argument to pass a data frame to the function's environment and do everything locally. By not making any assignment at the end, we implicitly tell the function to return it's result.
Then, in your loop, instead of simply calling writedata, we assign it's result back to baskets.df to replace the previous result.
for(i in 1:length((user_data)))
{
for(j in i:length(user_data))
{
if(user_data$challenge_sequence[i] == user_data$challenge_sequence[j] &&
user_data$challenge[i] == user_data$challenge[j])
{
baskets.df <- writedata(baskets.df,
user_data$challenge_sequence[i],
user_data$challenge[i])
}
}
}
writedata=function(data, seqnn,challng)
{
#print(seqnn)
#print(challng)
newRow <- data.frame(Sequence = seqnn,
Challenge = challng,
countno = 1)
rbind(data, newRow)
}
I'm not sure what you're programming background is, but your loops will be very slow in R because it's an interpreted language. To get around this, many functions are vectorized (which simply means that you give them more than one data point, and they do the looping inside compiled code where the loops are fast).
With that in mind, here's what I believe will be a much faster implementation of your code
user_data=read.csv("train_5.csv")
# challenge_indices will be a matrix with TRUE at every place "challenge" and "challenge_sequence" is the same
challenge_indices <- outer(user_data$challenge_sequence, user_data$challenge_sequence, "==") &
outer(user_data$challenge, user_data$challenge, "==")
# since you don't want duplicates, get rid of them
challenge_indices[upper.tri(challenge_indices, diag = TRUE)] <- FALSE
# now let's get the indices of interest
index_list <- which(challenge_indices,arr.ind = TRUE)
# now we make the resulting data set all at once
# this is much faster, because it does not require copying the data frame many times - which would be required if you created a new row every time.
baskets.df <- with(user_data, data.frame(
Sequence = challenge_sequence[index_list[,"row"]],
challenge = challenge[index_list[,"row"]]
)
I am trying to create a data frame of various error messages based on Data to be cross checked between two dataframes and storing the message in a vector in an iterative manner . I am using the following snippet for this purpose :
> for(j in 1:nrow(MySQL_Data)){ date_mysql=
> paste("MySQL_Data[",j,",1]") date_red= paste("RED_Data[",j,",1]")
> body= c() if(!date_mysql == date_red) {
> body<- append(body,paste("'There is data missing for date",date_mysql,"in",table2)) }else {
> NULL }}
My table2 variable prints as MYSQL_Data[2,1] instead of the actual value of the variable which is a date
Following is the Output :
"'There is data missing for date MySQL_Data[ 2 ,1] in Dream11_UserRegistration"
Can someone help me with the error that I am committing here..
Thanks in Advance !
Your use of paste in the definitions of data_mysql and data_red makes no sense. I’m assuming that what you actually want is this:
data_mysql = MySQL_Data[j, 1]
data_red = RED_Data[j, i]
Furthermore, you’re resetting body in every loop iteration so it will only ever hold a single element.
I am trying to implement following algorithm in R:
Iterate(Cell: top)
While (top != null)
Print top.Value
top = top.Next
End While
End Iterate
Basically, given a list, the algorithm should break as soon as it hits 'null' even when the list is not over.
myls<-list('africa','america south','asia','antarctica','australasia',NULL,'europe','america north')
I had to add a for loop for using is.null() function, but following code is disaster and I need your help to fix it.
Cell <- function(top) {
#This algorithm examines every cell in the linked list, so if the list contains N cells,
#it has run time O(N).
for (i in 1:length(top)){
while(is.null(top[[i]]) !=TRUE){
print(top)
top = next(top)
}
}
}
You may run this function using:
Cell(myls)
You were close but there is no need to use for(...) in this
construction.
Cell <- function(top){
i = 1
while(i <= length(top) && !is.null(top[[i]])){
print(top[[i]])
i = i + 1
}
}
As you see I've added one extra condition to the while loop: i <= length(top) this is to make sure you don't go beyond the length of the
list in case there no null items.
However you can use a for loop with this construction:
Cell <- function(top){
for(i in 1:length(top)){
if(is.null(top[[i]])) break
print(top[[i]])
}
}
Alternatively you can use this code without a for/while construction:
myls[1:(which(sapply(myls, is.null))[1]-1)]
Check this out: It runs one by one for all the values in myls and prints them but If it encounters NULL value it breaks.
for (val in myls) {
if (is.null(val)){
break
}
print(val)
}
Let me know in case of any query.