My intention is to use a for loop to apply a function to several datasets, while saving the output as .csv files.
I'm going to present a simple example, which I'm sure can be solved in other ways, but it's just to try to illustrate what I need to do with slightly more complicated data and functions:
I have the following datasets:
df1 = data.frame(ID_INDIVIDUO = c("individo_1", "individo_2", "individo_3", "individo_4", "individo_5", "individo_6", "individo_7"),
ciudad = c("Ciudad_A", "Ciudad_A", "Ciudad_B", "Ciudad_C", "Ciudad_C", "Ciudad_D", "Ciudad_A"))
df2 = data.frame(ID_INDIVIDUO = c("individo_1", "individo_4", "individo_5", "individo_6", "individo_7"),
ciudad = c("Ciudad_A", "Ciudad_C", "Ciudad_C", "Ciudad_D", "Ciudad_A"))
And the following function:
mi_funcion <- function(x){
Casos_ciudad_A <- x %>% filter(ciudad == "Ciudad_A")
return(Casos_ciudad_A)
}
To make a list of the datasets to use, I do:
archivos <- mget(ls()[grep("df", ls())])
And here I come. I can see the results I want by doing:
for (i in archivos){
print(mi_funcion(i))
}
But I am not able to export the results of each dataset to two separate files. This was my attempt, which gives an error:
for (i in archivos){
write.csv(mi_funcion(i),paste(names(archivos [i]), ".csv", sep = ","))
}
Specifically, the error is: "Error in files[i] : invalid subscript type 'list'". I would greatly appreciate any help you can guide me on this. Cheers!
welcome. I think the problem is that you use the list itself as an iterator. I understand that in R it can be done (although it looks like Python code rather than R), but the most common practice is to synchronize the loop using position. So you have to explicitly generate the iterator.
This loop works.
Use
seq_along()
to generate a sequence of integers from 1 tolength(archivos)
. By that index iteratesfor
and synchronizes the listarchivos
with the names of the listarchivos
. I think that was the problem, in the subset ofnames(archivos)[i]
you were passing the data frame asi
, and noti
as an index number.names(archivos)
is a character string, the subset has to be made with numbers or another character string that matches the names.If you prefer to use functional programming instead of loops, an alternative is this:
walk()
it is a functional. It is similar tolapply()
, it takes care of passing another function with a syntax~fun(.x)
over a list. Each element of the list is evaluated in the function as.x
. The peculiarity ofwalk()
is that it does not produce output itself and so it is better to use it when you want to produce a side effect as in~print(.x)
,~write.algo(.x)
,~plot(.x)
.iwalk
is similar, except that it allows you to use a.y
as the second argument to the function. In this case.y
they are always the names of the list.x
. It is not necessary to callnames(.x)
, they are already there asy.
It is convenient for cases like this, it is also used to make many graphics and put the titles, title tables, etc.