Why using two variables in loop in R (code given below)? - r

I am looking at DIGRE model code in R and there is a loop as follow:
idx <- 1
for (i in 1:length(drugName)) {
if (drugName[i] != "Neg_control") {
cat(idx, ". ", drugName[i], "\n", sep = "")
idx <- idx + 1
}
My question is a particular reason for using separate variables ( i and idx ) for loop and the counter. Wouldn't this loop work fine with just one variable. I am new to R therefore curious.

The variable idx only gets incremented if drugName isn't "Neg_control". So i indexes all the observations of drugName and idx counts the 'occurences'. I guess depending on how the data looks like and what the goal of the function is, this could be done without using a loop.

How about this?
controlTF = drugName != "Neg_control"
idx <- sum(controlTF)
paste0(1:idx, ". ", drugName[controlTF])

Related

While loop nested in for loop R

I am trying to pull out individual subject data in R using a for and while loop. I would like for the loop to pull the data accordingly and save it as it's own data file. The issue is the for loop not counting Subjects properly and returning the proper value for b. My while loop works perfectly because I can manually set the value of b, run the loop, and produce the correct data files.
Subjects = (1:2)
r = (1);
ST = (d$onReadyTime) #need to get ST to read not just the first number in onReadyTime for each trial
ST=strsplit(ST,split = "a")
for (b in (1:length(Subjects)){
b <- Subjects[r]
while (r == Subjects[b])
{STSubject = (ST[[b]])
ST2=(STSubject)
#ST2=`colnames<-`(ST2,Subjects[i])
write.table(ST2,file = paste("ST_Subject_",b,".csv",sep=""),row.names = FALSE, col.names= TRUE)
r = r+1
}
}
Without a minimum working example, only general guidance can be offered.
n <- 0
for (i in seq_along(models)) {
for (j in seq_along(meters)) {
n <- n + 1
make_line(i, j) -> glances[[n]]
}
}
The key point here, as remarked, is to initialize the counter outside the inner loop.

Create new columns in data table with for loop

Is there a simple way to create columns within a for loop? I know this question has been asked here multiple times and I have tried this solution adjusted to my case
for (i in 1:100) {
eval(parse(text = paste0('a$colum', i, ' <- whatever_you_want_your_column_to_contain')))
}
from one of the posts, but it did not help. I have an existing data table data and I am trying to create columns P_1 to P_30 within a for loop and then assign them NULL (I am just trying to pre-define the columns). I have tried this:
for (i in 1:30) {
eval(parse(text = paste0('data$P_', i, ' <- NULL')))
}
but without any success. Can you please suggest any approach that would work?
A related question - how to refer to those columns in another loop, if I have again column P_i where i is from 1 to 30, how to refer to data$P_i within a loop?
Edit:
I have this data table to make an example:
customer_id <- c("1","1","1","2","2","2","2","3","3","3")
account_id <- as.character(c(11,11,11,55,55,55,55,38,38,38))
obs_date <- c(as.Date("2017-01-01","%Y-%m-%d"), as.Date("2017-02-01","%Y-%m-%d"), as.Date("2017-03-01","%Y-%m-%d"),
as.Date("2017-12-01","%Y-%m-%d"), as.Date("2018-01-01","%Y-%m-%d"), as.Date("2018-02-01","%Y-%m-%d"),
as.Date("2018-03-01","%Y-%m-%d"), as.Date("2018-04-01","%Y-%m-%d"), as.Date("2018-05-01","%Y-%m-%d"),
as.Date("2018-06-01","%Y-%m-%d"))
variable <- c(87,90,100,120,130,150,12,13,15,14)
data <- data.table(customer_id,account_id,obs_date,variable)
and I found out that the problem is really in assigning that NULL to those columns, because when I am doing this based on the post's advice:
for (i in 1:30) {
eval(parse(text = paste0('data$P_', i, ' <- 1')))
}
it really works, just with the NULL instead of 1 it does not. So, it is not a bad advice, it just does not work with NULL.
Here's a data.table answer - I think you were close, you just didn't have the right syntax to append a column to a data table:
for (i in 1:30) {
data[, paste0("P_", i) := "whatever_you_want_your_column_to_contain"]
}

R: Concatenate rows to make an statement for any dimension

I¨m trying to convert somo variables to statements.
I´m loonking for some variables in a data frame like that:
y<-subset(x,x$Incidence.type == "Appro.11.Plural")
Invoice Incidence.type
1: 20171200738 Appro.11.Plural
2: 20171200737 Appro.11.Plural
Once it is done, I would like to set an statement like that:
Statement<-paste("The invoices",y[1,2],"and",y[2,2], "are...")
The problem is that the number of elements, instead of two, could be from 0 to infinite. So, I need to generalize this code to achieve an equivalent result, whatever the number of invoices.
I´ve try that, but still not working:
if (length(y>0) {for (j in (Push$Invoice)) {Statement<-paste(j,sep = ",")}}
Thanks in advance.
0 and 1 are special cases, anything 2 and over we can generalize.
if (nrow(y) > 0) Statement = "No matches."
if (nrow(y) == 1) Statement = paste("The invoice", y[1, 2], "is ...")
if (nrow(y) > 1) {
invoices = paste(y[, 2], collapse = ", and ")
Statement = paste("The invoices", invoices, "are ...")
}
I've mimicked your question using the second column of y, but don't you actually want the invoice number? For more robust code I'd recommend using the column name: y[1, "Invoice"] instead of y[1, 1], that way you will always get the correct column even if the order is different. If you are using data.table you don't need to quote the column name.

Substituting variables in a loop?

I am trying to write a loop in R but I think the nomenclature is not correct as it does not create the new objects, here is a simplified example of what I am trying to do:
for i in (1:8) {
List_i <-List
colsToGrab_i <-grep(predefinedRegex_i, colnames(List_i$table))
List_i$table <- List_i$table[,predefinedRegex_i]
}
I have created 'predefinedRegex'es 1:8 which the grep should use to search
The loop creates an object called "List_i" and then fails to find "predefinedRegex_i".
I have tried putting quotes around the "i" and $ in front of the i , also [i] but these do not work.
Any help much appreciated. Thank you.
#
Using #RyanGrammel's answer below::
#CREATING regular expressions for grabbing sets groups 1 -7 ::::
g_1 <- "DC*"
g_2 <- "BN_._X.*"
g_3 <- "BN_a*"
g_4 <- "BN_b*"
g_5 <- "BN_a_X.*"
g_6 <- "BN_b_X.*"
g_7 <- "BN_._Y.*"
for i in (1:8)
{
assign(x = paste("tableA_", i, sep=""), value = BigList$tableA)
assign(x = paste("Forgrep_", i, sep=""), value = colnames(get(x = paste("tableA_", i, sep=""))))
assign(x = paste("grab_", i, sep=""), value = grep((get(x = paste("g_",i, sep=""))), (get(x = paste("Forgrep_",i, sep="")))))
assign(x = paste("tableA_", i, sep=""), value = BigList$tableA[,get(x = paste("grab_",i, sep=""))])
}
This loop is repeated for each table inside "BigList".
I found I could not extract columnnames from
(get(x = paste("BigList_", i, "$tableA" sep=""))))
or from
(get(x = paste("BigList_", i, "[[2]]" sep=""))))
so it was easier to extract the tables first. I will now write a loop to repack the lists up.
Problem
Your syntax is off: you don't seem to understand how exactly R deals with variable names.
for(i in 1:10) name_i <- 1
The above code doesn't assign name_1, name_2,....,name_10. It assigns "name_i" over and over again
To create a list, you call 'list()', not List
creating a variable List_i in a loop doesn't assign List_1, List_2,...,List_8.
It repeatedly assigns an empty list to the name 'List_i'. Think about it; if R names variables in the way you tried to, it'd be equally likely to name your variables L1st_1, L2st_2...See 'Solution' for some valid R code do something similar
'predefinedRegex_i' isn't interpreted as an attempt to get the variable 'predefinedRegex_1', 'predefinedRegex_2', and so one.
However, get(paste0("predefinedRegex_", i)) is interpreted in this way. Just make sure i actually has a value when using this. See below.
Solution:
In general, use this to dynamically assign variables (List_1, List_2,..)
assign(x = paste0("prefix_", i), value = i)
if i is equal to 199, then this code assigns the variable prefix_199 the value 199.
In general, use this to dynamically get the variables you assigned using the above snippet of code.
get(x = paste0("prefix_", i))
if i is equal to 199, then this code gets the variable prefix_199.
That should solve the crux of your problem; if you need any further help feel free to ask for clarification here, or contact me via my Twitter Feed.

combine results from loop in one file in R (some results were missing)

I want to combine the results from a for loop into 1 txt file and I have written my code based on suggestion from this link
combine results from a loop in one file
There is one problem. I am supposed to get 8 results (row) but I only ended with only 5. Somehow the other results did not get into the file. I think the problem is with the if statement but I don't know how to fix it.
Here is my code
prob <- c(0.10, 0.20)
for (j in seq(prob)) {
range <- c(2,3)
for (i in seq(range)) {
sample <- c(10,20)
for (k in seq(sample)) {
data <- Simulation(X =1,Y =range[i], Z=sample[k] ,p = prob[j])
filename <- paste('file',i,'txt')
if (j == 1) {
write.table(data, "Desktop/file2.txt", col.names= TRUE)
} else {
write.table(data,"Desktop/file2.txt", append = TRUE, col.names = FALSE)
}
}
}
}
That's because the if ( j == 1 ) bit is meant to check whether this is the first time you've written to the file or not.
If it is the first time, then it will write the column names (i.e. X, Y, Z, p) into the file (see the col.names=TRUE?).
If it isn't the first time, then it won't write the column names, but will just append the data.
Since you have multiple nested loops, that condition won't work so well for you: when j==1 (i.e. for prob=0.1) you perform 4 other loops within. But since j==1, the data is getting overwritten each time.
I'd recommend initialising a variable count that counts how many times you've performed Simulation, and then changing that line to if ( count == 1 ):
count <- 1
prob <- c(0.10,0.20)
# .... code as before
data <- Simulation(X =1,Y =range[i], Z=sample[k] ,p = prob[j])
if ( count == 1 ) {
write.table(data, "Desktop/file2.txt", col.names=T)
} else {
write.table(data, "Desktop/file2.txt", append=T, col.names=F)
}
# increment count
count <- count + 1
}}}

Resources