Create a series of new folders in for loop in R - r

I have create a small script that passes a vector through a loop. In this loop I am using an if else statement to check if folder exists and if not to create the folder. However, I am getting error: Error in file.exists(i) : invalid 'file' argument. This has to due with file.exist(). I dont understand why this isnt ok. I check the man using help. Seems like this should be working.
folders<- c("RawData", "Output", "BCV", "DEplots", "DEtables", "PathwayOuts", "VolcanoPLots")
for(i in 1:length(folders)){
if (file.exists(i)){
cat(paste0(i, "already exists"))
} else {
cat(paste0(i, "does not exists"))
dir.create(i)
}
}

You are looping over an index (that is, 1:length(folders) is just the vector 1:7, not the values of the folders vector itself. The easiest solution is to loop over the vector itself:
for (i in folders) {
Or, if you still want to loop over the index:
for (i in 1:length(folders)) {
if (file.exists(folders[i])){
cat(paste0(folders[i], "already exists"))
}
else {
cat(paste0(folders[i], "does not exists"))
dir.create(folders[i])
}
}
A quick tip: if you are debugging a for-loop, the place to start is to add print(i) at the start of the loop. You would have immediately seen the problem: i was an integer, not the first value of the vector.

Related

Multiple if statements in a for loop - R

I am trying to create a for loop that goes through each URL in (recipe_urls) and if it contains a certain domain, a function I wrote for scraping the recipe off the website will run. I have never tried nesting if statements within a for loop before, so I think that might be the root of the problem.
for (recipe_url in recipe_urls) {
if ("allrecipes.*" %rin% recipe_urls == "TRUE"){
scrape_allrecipes(recipe_url)
}
if("foodnetwork.*" %rin% recipe_urls == "TRUE"){
scrape_allrecipes(recipe_url)
}
}
Note: %rin% is a custom function to return true or false if a partial match (e.g., "allrecipes" is present within the URL):
`%rin%` = function (pattern, list) {
vapply(pattern, function (p) any(grepl(p, list)), logical(1L), USE.NAMES = FALSE)
}
Interestingly, the allrecipes one works but duplicates everything twice (I have it set to print in a .txt file). However the foodnetwork does not seem to run.
Individually, this works to return recipes from URL:
recipes <- for (recipe_url in recipe_urls) {
scrape_allrecipes(recipe_url)
}
In my infinite wisdom, I accidentally was calling the same function in the second if statement. Works now, oops!

Length Zero in r

Greetings I am getting an error of
Error in if (nrow(pair) == 0) { :argument is of length zero
I have checked the other answers but do not seem to work on a variable like mine. Please check code below, please assist if you can.
pair<-NULL
if(exists("p.doa.ym")) pair <- rbind(pair, p.doa.ym[,1:2])
if(exists("p.doa.yd")) pair <- rbind(pair, p.doa.yd[,1:2])
if(nrow(pair) == 0) {
print("THERE ARE NO MATCHES FOR TODAY. STOP HERE")
quit()
}
Since you set pair=NULL and then it might happen that pair stays null if those two if statements are not true, you either need to check if pair is null first, or you could set pair to an empty data frame, or something else.
One option:
if (!is.null(pair)) {
if (nrow(pair)==0) {
# your code
}
}
Another option:
pair=data.frame()
# your code

How to handle variable not defined error in r

Is there a way to evade variable not defined error in r? For example the code below throws variable not defined error.
for(i in length(someList)){
print(someList[[i]])
}
Can I check if a variable exists first before executing the code above. A pseudocode would look like this:
if(someList exists){
for(i in length(someList)){
print(someList[[i]])
}
} else cat("The variable does not exist")
Are you looking for the exists function?
someList <- list(1,2,3)
if (exists("someListNot")){
for(i in length(someListNot)){
print(someListNot[[i]])
}
}
if (exists("someList")){
for(i in 1:length(someList)){
print(someList[[i]])
}
}
You can use the exists("myVariable") function to check existence.
Also make sure your loop is really looping! If you use for (i in length(variable) it will only use the last index of your variable instead of looping over it.
You code could look something like this:
if ( exits("myVariable")){
for(i in seq_len(length(someList))){
print(someList[[i]])
}
}

Loop works outside function but in functions it doesn't.

Been going around for hours with this. My 1st question online on R. Trying to creat a function that contains a loop. The function takes a vector that the user submits like in pollutantmean(4:6) and then it loads a bunch of csv files (in the directory mentioned) and binds them. What is strange (to me) is that if I assign the variable id and then run the loop without using a function, it works! When I put it inside a function so that the user can supply the id vector then it does nothing. Can someone help ? thank you!!!
pollutantmean<-function(id=1:332)
{
#read files
allfiles<-data.frame()
id<-str_pad(id,3,pad = "0")
direct<-"/Users/ped/Documents/LearningR/"
for (i in id) {
path<-paste(direct,"/",i,".csv",sep="")
file<-read.csv(path)
allfiles<-rbind(allfiles,file)
}
}
Your function is missing a return value. (#Roland)
pollutantmean<-function(id=1:332) {
#read files
allfiles<-data.frame()
id<-str_pad(id,3,pad = "0")
direct<-"/Users/ped/Documents/LearningR/"
for (i in id) {
path<-paste(direct,"/",i,".csv",sep="")
file<-read.csv(path)
allfiles<-rbind(allfiles,file)
}
return(allfiles)
}
Edit:
Your mistake was that you did not specify in your function what you want to get out from the function. In R, you create objects inside of function (you could imagine it as different environment) and then specify which object you want it to return.
With my comment about accepting my answer, I meant this: (...To mark an answer as accepted, click on the check mark beside the answer to toggle it from greyed out to filled in...).
Consider even an lapply and do.call which would not need return being last line of function:
pollutantmean <- function(id=1:332) {
id <- str_pad(id,3,pad = "0")
direct_files <- paste0("/Users/ped/Documents/LearningR/", id, ".csv")
# READ FILES INTO LIST AND ROW BIND
allfiles <- do.call(rbind, lapply(direct_files, read.csv))
}
ok, I got it. I was expecting the files that are built to be actually created and show up in the environment of R. But for some reason they don't. But R still does all the calculations. Thanks lot for the replies!!!!
pollutantmean<-function(directory,pollutant,id)
{
#read files
allfiles<-data.frame()
id2<-str_pad(id,3,pad = "0")
direct<-paste("/Users/pedroalbuquerque/Documents/Learning R/",directory,sep="")
for (i in id2) {
path<-paste(direct,"/",i,".csv",sep="")
file<-read.csv(path)
allfiles<-rbind(allfiles,file)
}
#averaging polutants
mean(allfiles[,pollutant],na.rm = TRUE)
}
pollutantmean("specdata","nitrate",23:35)

R code does not work when called from function

HI i just started learning R and finding this problem to be really interesting where I just run a code directly without wrapping in a function it works but when I place it inside a function it doesn't work, What can be possible reason?
fill_column<-function(colName){
count <- 0
for(i in fg_data$particulars) {
count <- count +1
if(grepl(colName, i) && fg_data$value[count] > 0.0){
fg_data[,colName][count] <- as.numeric(fg_data$value[count])
} else {
fg_data[,colName][count] <- 'NA'
}
}
}
fill_column('volume')
Where I am creating new column named volume it this string exists in particulars column.
I have added a comment where solution given by another question does not work for me, Please look at my comment below.
Finally I got it working but reading another answer on SO, here is the solution:
fill_column <- function(colName){
count <- 0
for(i in fg_data$particulars) {
count <- count +1
if(grepl(colName, i) && fg_data$value[count] > 0.0){
fg_data[,colName][count] <- as.numeric(fg_data$value[count])
} else {
fg_data[,colName][count] <- 'NA'
}
}
return(fg_data)
}
fg_data = fill_column('volume')
Now reason, Usually in any language when we modify global object inside any function it reflects on global object immediately but in R we have to return the modified object from function and then assign it again to global object to see our changes. or another way for doing this is to assign local object from within the function to global context using envir=.GlobalEnv.

Resources