1

I'm trying to get a for loop to generate multiple smaller dataframes from a large dataframe:

Year <- rep(1995:2012,4)
Name <- rep(LETTERS[1:4],18)
abc <- data.frame(Year,Name)


for (year in 1995:2012) {
  assign(paste("dff",year,sep=""), abc[abc$Year == year,])
  #paste("dff",year,sep="") <- paste("dff",year,sep="")[with(paste("dff",year,sep=""), order(Name)), ]
}

Problem is the last (commented) line which when uncommented throws an error:

invalid 'envir' argument of type 'character'.

What can I do to fix this? I'm basically trying to order the dataframe by the column Name.

1
  • You can't make a <- assignment to a character string resulting from paste. (You didn't do it in the line above---you used assign for that purpose!) A couple ideas: (a) sort the data frame by Name before the loop. (b) Use a list of data frames instead: abc_list = split(abc, abc$Year) and then to sort: abc_list = lapply(abc_list, function(x) x[order(x$Name), ]). See, e.g., how to make a list of data frames. Commented Feb 23, 2017 at 22:57

2 Answers 2

2

Either you use list() or adapt your code the following way:

Year <- rep(1995:2012,4)
Name <- rep(LETTERS[1:4],18)
abc <- data.frame(Year,Name)


for (year in 1995:2012) {
  assign(paste("dff",year,sep=""), abc[abc$Year == year,])
  assign((paste("dff",year,sep="")), get(paste("dff",year,sep=""))[with(get(paste("dff",year,sep="")), order(Name)), ])
}
Sign up to request clarification or add additional context in comments.

Comments

2

Just in the interest of providing a couple of extra options, or If you were interested in using lists, and or avoiding using assign we could do the following:

library(data.table)

Year <- rep(1995:2012,4)
Name <- rep(LETTERS[1:4],18)
abc <- data.frame(Year,Name)

abc <- data.table(abc)
my_list <- split(abc, Year)
my_list <- lapply(my_list, function(x){x[order(Name)]})

Pretty simple, avoids using get and assign. split gets rid of the need to loop things to split the data table up as well. Might be easier to read/understand too.

If you wanted to stick to something using a for loop, i.e. what you had initially, you could do:

empty_list <- list()

for(i in unique(abc[,Year])){
  empty_list[[paste0(i)]] <- abc[Year == i,]
  empty_list[[paste0(i)]] <- empty_list[[paste0(i)]][order(Name)]
}

Someone might be able to write a cleaner loop than above, but it works!

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.