I have a couple of columns named "Lab1Date", "Lab3Date" "Lab7Date" etc and more column of the same pattern - the integer changes but not the rest of the string. I can generate a vector with such column names using a for loop easily, like
for (j in c(1,3,7,14,28)) {
newcolorder <- c(newcolorder,paste0("Lab",j,"Date"))
}
But I was wondering whether there was a more elegant, idiomatic way in R, maybe using the likes of rep().
Thanks.
You can use paste directly without a for loop as paste is vectorized.
paste0('Lab', c(1,3,7, 14,28), 'Date')
Related
I have several dataframes and would like to add columns with a loop. At the moment the code looks like this:
FR1$MONTH<-'2015-01'
FR2$MONTH<-'2015-02'
FR3$MONTH<-'2015-03'
FR4$MONTH<-'2015-04'
I have tried the following:
for (i in 1:12) {
assign(paste("FR",i,$,"MONTH",sep=""),paste("2015-",i,sep=""))
}
Unfortunatly it doesnt work.
Can anybody tell me what is wrong with my try, or even better: How to do this right as I suspect a loop isnt the best solution.
Well, one issue that would throw you an error is that the '$' should be within quotes within the first paste() call.
I would try, however:
eval(parse(text = paste0("FR", i, "$MONTH <- 2015-", i)))
within your loop. And you may want to use an ifelse() to get the 0 in the month when you need it.
And I second Colonel's comment about keeping your data.frames within some other data structure.
I don't know how to write for-loops in r. Here is what I want to do:
I have a df called "na" with 50 columns (ana1_1:ana50_1). I want to loop these commands over all columns. Here are the commands for the first two columns (ana1_1 and ana2_1):
t<-table(na$ana1_1)
ana1_1<-capture.output(sort(t))
cat(ana1_1,file="ana.txt",sep="\n",append=TRUE)
t<-table(na$ana2_1)
ana2_1<-capture.output(sort(t))
cat(ana2_1,file="ana.txt",sep="\n",append=TRUE)
After the loop, all tables (ana1_1:ana50_1) should be written in ana.txt Has anyone an idea, how to solve the problem? Thank you very much!
One approach would be to loop through the columns with lapply and using the same code as in the OP's post
invisible(lapply(na, function(x) {
x1 <- capture.output(sort(table(x)))
cat(x1, file='ana.txt', sep="\n", append=TRUE)
}))
Wrapping with invisible so that it won't print 'NULL' in the R console.
We can wrap with a condition to check if the file already exists so that it won't add the same lines by accidentally running the code again.
if(!file.exists('ana.txt')){
invisible( lapply(na, function(x) {
x1 <- capture.output(sort(table(x)))
cat(x1, file='ana.txt', sep="\n", append=TRUE)
}))
}
Here is a solution with a for loop. Loops tend to be slow in r so people prefer other solutions (e.g. the great answer provided by akrun). This answer is for your understanding of the loop syntax:
for(i in 1:50){
t1<-table(na[,i])
t2<-capture.output(sort(t1))
cat(t2,file="ana.txt",sep="\n",append=TRUE)
}
We are looping through i from 1 to 50 (first line). To select a column there's two (there's actually more than two, but that's for another time) ways to access it: na$ana1_1 or na[,1] both select the first column (second line). In the first case you refer by column name, in the second by column index. Here the second case is more convenient. The rest is your desired calculations.
Be aware that cat creates a new file if ana.txt is not existing yet and appends to it if it is already there.
I have stored a list of names as characters and want to convert them to something that can be accepted as data frame name. something like this:
for (i in 1:18) {
str[i] <- paste("alert_month_amount_",i,sep="")
}
name_str = as.character(str)
then name_str will be:
name_str[1] would be "alert_month_amount_1"
now i want to assign certain data to a data frame that uses name_str[i] inside a loop like:
for (n in 1:18){
name_str[n] <- subset(by_Month_Acct_Num,month==month_index[n] & year==year_index[n])
}
but this does not work perhaps because the names are passed as characters inside double quotation mark ("). I would appreciate your help.
You can use assign for this:
assign(name_str[n], subset(by_Month_Acct_Num,month==month_index[n] & year==year_index[n]))
This is FAQ 7.21. The most important part of that answer is the end where it says (like #MrFlick) that it is better to use a list. You really should learn how to take advantage of R's vectorized functions.
The paste and paste0 functions are both vectorized, so your first bit of code can be replaced with:
name_str <- paste0("alert_month_amount_", 1:18)
without need for the loop.
You could create your list and fill it with code like:
alert_month_amount <- list()
for(i in 1:18) {
alert_month_amount[[i]] <- subset(by_Month_Acct_Num,month==month_index[n] & year==year_index[n])
}
Or possibly even easier using the split function. You could also use lapply or mapply.
If you want the elements named then just do:
names(alert_month_amount) <- name_str
Now with everything in a single list you can copy, save, delete, etc. one object rather than needing another loop to do each individual piece. If you want to do the same thing (calculate a summary, fit a regression, etc.) on each piece created then with everything in a list you can just use lapply or sapply on the list rather than having to create another loop and figuring out how to grab each piece in the loop and save it to an output object.
Is there a way to have the object name become the file name character string when using write.table or write.csv?
In the following, a and b are vectors. I will be doing similar comparisons for many other pairs of vectors, and would like to not write out the object name as many times as I have been doing.
unique_downa<-a[!(a%in%b)]
write.csv(unique_downa,file="unique_downa.csv")
Or if anyone has a suggestion for a better way to do this whole process, I'd be happy to hear it.
The idiomatic approach is to use deparse(substitute(blah))
eg
write.csv.named <- function(x, ...){
fname <- sprintf('%s.csv',deparse(substitute(x)))
write.csv(x=x, file = fname, ...)
}
It might be easiest to use the names of elements of a list instead of trying to use object names:
mycomparisons <-list (unique_downa = a[!(a%in%b)], unique_downb = b[!(b%in%a)])
mapply (write.csv, mycomparisons, paste (names (mycomparisons), ".csv", sep =""))
The best thing to do is probably put your vectors in a list, and then do the comparisons, the naming, and the writing out all inside the same loop, but that depends on how similar these similar comparisons are...
Assume:
list of n xts objects in .GlobalEnv with the suffix ".raw" (e.g: ABC.raw)
have created a list of .raw names in a list (ie, rawfiles <- ls(pattern="*.raw",envir=.GlobalEnv))
Would like to:
loop or lapply through rawfiles and subset a particular timeperiod in each iteration
for example, to write this as a single line would be: new <- ABC.raw["T09:00/T10:00"] if I wanted to subset ABC.raw from 9am to 10am each day.
The problem is:
Doesn't seem to be an easy way of passing["Thh:mm/Thh:mm"] to a loop, apply or assign without causing errors.
Any ideas how to pass this?
In pidgeon code, I guess I'm looking for a working equivalent of:
for(i in 1:length(raw)){
raw[i]["T09:00/T10:00"]
}
Many thanks in advance for any assistance on this.
Try get.
get(x) retrieves the variable whose name is stored in x, so foo<-1; get('foo') would return 1.
for ( rawname in rawfiles ) {
get(rawname)["T09:00/T10:00"]
}