Apply some function to a variable from its string name - r

I've got a list of strings list = c("string_1", "string_2", ...) and, based on this vector, I know there are dataframes named df_string_1, df_string_2, ... in my environment.
My code is like:
for (i in 1:length(list)){
res = function(i) // dataframe depending on i, same ncol as df_string_i
rbind(df_list[i],res) // that's the line I don't know how to code
}
I can't find a way to get the dataframe df_string_i at each iteration.
My attempt was to get its name with paste("df_",list[i],sep="") but then, what can I do with this string as I need the variable to be in the rbind?
Thanks for your help!

If you have a situation with data.frames named df_string_1, ..., df_string_n, you would be better off, in the long run, storing these in a list and using tools such as lapply. To solve the current issue, use get:
for (i in 1:length(list)){
res = function(i) // dataframe depending on i, same ncol as df_string_i
rbind(get(paste0("df_",list[i])),res)
}

Related

Defining multiple dataframes with for loop from list object

Very green R user here. Sorry if this is asked and answered somewhere else, I haven't been able to find anything myself.
I can't figure out why I can't get a for loop to work define multiple new dataframes but looping through a predefined list.
My list is defined from a subset of variable names from an existing dataframe:
varnames <- colnames(dplyr::select(df_response, -1:-4))
Then I want to loop through the list to create a new dataframe for each variable name on the list containing the results of summary function:
for (i in varnames){
paste0("df_",i) <- summary(paste0("df$",i))
}
I've tried variations with and without paste function but I can't get anything to work.
paste0 returns a string. Both <- and $ require names, but you can use assign and [[ instead. This should work:
varnames <- colnames(dplyr::select(df_response, -1:-4))
for (i in varnames){
assign(
paste0("df_", i),
summary(df[[i]])
)
}
Anyway, I'd suggest working with a list and accessing the summaries with $:
summaries <- df_response |>
dplyr::select(-(1:4)) |>
purrr::imap(summary)
summaries$firstvarname

Loop for on dataset name in R

This topic has been covered numerous times I see but I can't really get the answer I'm looking for. Thus, here I go.
I am trying to do a loop to create variables in 5 data sets that have similar names as such:
Ech_repondants_nom_1
Ech_repondants_nom_2
Ech_repondants_nom_3
Ech_repondants_nom_4
Ech_repondants_nom_5
Below if the code that I have tried:
list <- c(1:5)
for (i in list) {
Ech_repondants_nom_[[i]]$sec = as.numeric(Ech_repondants_nom_[[i]]$interviewtime)
Ech_repondants_nom_[[i]]$min = round(Ech_repondants_nom_[[i]]$sec/60,1)
Ech_repondants_nom_[[i]]$heure = round(Ech_repondants_nom_[[i]]$min/60,1)
}
Any clues why this does not work?
cheers!
These are object names and not list elements to subset as Ech_repondants_nom_[[i]]. We may need to get the object by paste i.e.
get(paste0("Ech_repondants_nom_", i)$sec
but, then if we need to update the original object, have to call assign. Instead of all this, it can be done more easily if we load the datasets into a list and loop over the list with lapply
lst1 <- lapply(mget(paste0("Ech_repondants_nom_", 1:5)), function(dat)
within(dat, {sec <- as.numeric(interviewtime);
min <- round(sec/60, 1);
heure <- round(min/60, 1)}))
It may be better to keep it as a list, but if we need to update the original object, use list2env
list2env(lst1, .GlobalEnv)
Ech_repondants_nom_[[i]]
Isn't actually selcting that dataframe because you can't call objects like that. Try creating a function that takes a dataframe as an argument then iterating through the dataframes
changing_time_stamp<-function(df){
df$sec = as.numeric(df$interviewtime)
df$min = round(df$sec/60,1)
df$heure = round(df$min/60,1)
for (i in list) {
changing_time_stamp(i)
}
EDIT: I fixed some of the variable names in the function

Referring to an object within a loop in R

I'm sure there is an easy answer. I have a loop, where for each iteration, I create a new vector to store the results. I do this by pasting a name together and then assigning that name to an empty vector.
for (i in seq(1, 50)) {
current_iteration = i
x = paste0("resultsVec", current_iteration)
assign(x, rep(NA, 43))
paste0("resultsVec", i)
for (j in seq(1, 100))
{
resultsVeci[j] = j * j # <- problem here
}
}
However, you obviously can't refer to 'resultsVeci' - so how to I refer to the iteration specific vector each loop?
If you do paste0("resultsVec", i), where i=2 for example, it returns a string "resultsVec2", rather than the object resultsVec2. How do I refer to the object rather than the string?
Thanks.
It really isn't a good idea to use get() and assign() with most R code. (Why is using assign bad?). Better to just use a list. A simple lapply would work here.
resultsVec<-lapply(1:50, function(i) (1:100)*(1:100))
and then you can get the values with reusltsVec[[1]], resultsVec[[2]], etc

How to use extract function in a for loop?

I am using the extract function in a loop. See below.
for (i in 1:length(list_shp_Tanzania)){
LU_Mod2000<- extract(x=rc_Mod2000_LC, y=list_shp_Tanzania[[i]], fun=maj)
}
Where maj function is:
maj <- function(x){
y <- as.numeric(names(which.max(table(x))))
return(y)
}
I was expecting to get i outputs, but I get only one output once the loop is done. Somebody knows what I am doing wrong. Thanks.
One solution in this kind of situation is to create a list and then assign the result of each iteration to the corresponding element of the list:
LU_Mod2000 <- vector("list", length(list_shp_Tanzania))
for (i in 1:length(list_shp_Tanzania)){
LU_Mod2000[[i]] <- extract(x=rc_Mod2000_LC, y=list_shp_Tanzania[[i]], fun=maj)
}
Do not do
LU_Mod2000 <- c(LU_Mod2000, extract(x=rc_Mod2000_LC, y=list_shp_Tanzania[[i]], fun=maj))
inside the loop. This will create unnecessary copies and will take long to run. Use the list method, and after the loop, convert the list of results to the desired format (usually using do.call(LU_Mod2000, <some function>))
Alternatively, you could substitute the for loop with lapply, which is what many people seem to prefer
LU_Mod2000 <- lapply(list_shp_Tanzania, function(z) extract(x=rc_Mod2000_LC, y=z, fun=maj))

How can I assign a function to a variable that its name should be made by paste function? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to name variables on the fly in R?
I have 10 objects of type list named: list1, list2, ..., list10. And I wanted to use the output from my function FUN to replace the first index of these list variables through a for loop like this:
for (i in 1:10){
eval(parse(test=(paste("list",i,sep=""))))[[1]] <- FUN()
}
but this does not work. I also used lapply in this way and again it is wrong:
lapply(eval(parse(text=(paste("list",i,sep=""))))[[1]], FUN)
Any opinion would be appreciated.
This is FAQ 7.21. The most important part of that FAQ is the last part that says not to do it that way, but to put everything into a list and operate on the list.
You can put your objects into a list using code like:
mylists <- lapply( 1:10, function(i) get( paste0('list',i) ) )
Then you can do the replacement with code like:
mylists <- lapply( mylists, function(x) { x[[1]] <- FUN()
x} )
Now if you want to save all the lists, or delete all the lists, you just have a single object that you need to work with instead of looping through the names again. If you want to do something else to each list then you just use lapply or sapply on the overall list in a single easy step without worrying about the loop. You can name the elements of the list to match the original names if you want and access them that way as well. Keeping everything of interest in a single list will also make your code safer, much less likely to accidentilly overwrite or delete another object.
You probably want something like
for (i in 1:10) {
nam <- paste0("list", i) ## built the name of the object
tmp <- get(nam) ## fetch the list by name, store in tmp
tmp[[1]] <- FUN() ## alter 1st component of tmp using FUN()
assign(nam, value = tmp) ## assign tmp back to the current list
}
as the loop.

Resources