Creating named list of large set of data frames R - r

This may be a trivial question, given I only have a few days' experience using R but basically i'd like to create a named list of data frames. I've seen a bunch of questions and answers dealing with only 2 data frames e.g
dataList <- list(x=data.frame1, y=data.frame2)
However i'm working with 48 data frames in this program and would like to know a more elegant way of creating a named list of 48 elements without actually explicitly naming all 48 of my data frames (which is what i've currently got):
dataList <- list(forecasted.data0=forecasted.data0, forecasted.data1=forecasted.data1, ...) and so on 46 more times.

Use the names or setNames function
> x <- as.list(rnorm(5))
> x
[[1]]
[1] -1.404512
[[2]]
[1] 0.927126
[[3]]
[1] 1.055555
[[4]]
[1] -1.718295
[[5]]
[1] 0.5154312
> names(x) <- paste0("forecasted.data.", seq(0, length(x) - 1))
> x
$forecasted.data.0
[1] -1.404512
$forecasted.data.1
[1] 0.927126
$forecasted.data.2
[1] 1.055555
$forecasted.data.3
[1] -1.718295
$forecasted.data.4
[1] 0.5154312

Would this work ?
forecasted.data0=data.frame(1)
forecasted.data1=data.frame(2)
n=ls()[grepl("^forecasted.data.*",ls())]
l=sapply(n, function(x) get(x))
names(l)=n
You can replace sapply with lapply if you prefer ...

Related

How do I force my vector to split into arguments?

I'm having problems with applying a function to a vector of arguments. The point is, none of the arguments are vectors.
I'm trying to apply my function with the do.call command, and my attempts go like this:
do.call("bezmulti", list(dat$t, as.list(getvarnames(n, "a"))))
where bezmulti is a function that takes in a vector (dat$t) and an indefinite number of single numbers, which are provided by the function getvarnames in the form of a vector, which I need to split.
The problem is that this list doesn't work the way I want it to - the way I would want would be:
[[1]]
#vector goes here
[[2]]
#the
[[3]]
#numbers
[[4]]
#go
[[5]]
#here
however my proposed solution, and all my other solutions provide lists that are either somehow nested or have only two elements, both of which are vectors. Is there a way to force the list to be in the format above?
EDIT: Functions used in this post look as follows
bezmulti <- function(t,...) {
coeff <- list(...)
n <- length(coeff)-1
sumco <- rep(0, length(t))
for (i in c(0:n)) {
sumco=sumco+coeff[[i+1]]*choose(n, i)*(1-t)^(n-i)*t^i
}
return(sumco)
}
getvarnames <- function(n, charasd) {
vec=NULL
for (j in c(1:n)) {
vec <- append(vec, eval(str2expression(paste0(charasd, as.character(j)))))
}
return(vec)
}
I think what you need to do is this:
do.call("bezmulti", c(list(dat$t), as.list(getvarnames(n, "a"))))
For example:
dat= data.frame(t = c(1,2,3,4,6))
c(list(dat$t), as.list(c(8,10,12)))
Output:
[[1]]
[1] 1 2 3 4 6
[[2]]
[1] 8
[[3]]
[1] 10
[[4]]
[1] 12

How do you make a vector of character strings from a vector of objects?

I want to generate a vector of character strings from a vector of objects.
Bob <- c(1,2,3,4)
Anne <- c(3,5,7,1)
Tim <- c(4,2,1,1)
People <- c(Bob, Anne, Tim)
Now what I want is:
> Names
[1] "Bob" "Anne" "Tim"
I know you can do this individually with
> deparse(substitute(Bob))
[1] "Bob"
So I tried to do
Names <- lapply(People,function(k){deparse(substitute(k))})
but this did not give the expected results. It produced a long list where each element is:
[[1]]
[1] "X[[i]]"
[[2]]
[1] "X[[i]]"
...
I'm sure this is a fairly easy task, but I can't get it working. Thanks!

How to save data.frames respectively in a list?

Here's my question. It's really appreciated if you can help.
I have a list containing several data.frames with different length but the same structure.
Now I want to save the data.frames in the list respectively.
Note: not combine them using do.call(rbind,...) into one single data.frame. And Also I want to name each of the data.frame in a array.
a=c(1,2,3,4,5,6)
b=c(4,5,6,5,5,5)
c=c(3,4,5,6,7,8)
A=data.frame(a=a,b=b,c=c)
B=data.frame(a=c,b=b,c=a)
C=data.frame(a=b,b=c,c=a)
l <- list(A, B, C)
names.list <- c("NewYear_Data", "Thanks_giving", "Christmas")
Now I want to save the A B C in the list using the name in names.list
To be specific, Here I have a list l, in which have several data.frames. Now I want to save each data.frames in the list l using the name in the names.list.
I tried unlist, and get, and apply...
It would be great if anyone can solve this using plyr, reshape, or data.table methods.
Thanks a lot!
Here is the solution
l <- list(A, B, C)
nms <- c("NewYear_Data", "Thanks_giving", "Christmas")
names(l) = nms
Now you can use names like this:
l$Christmas
If you want to get rid of the list, do this:
attach(l)
Christmas
To save them in a binary file:
save(list=nms,file='file.Rdata')
Or in a text files:
for( i in 1:length(l))
write.csv(l[i],paste0(nms[i],'.txt'))
Note to avoid calling your variable names.
If the question is, "How do I save a list of data frames as separate files in a folder?", you may try using saveRDS rather than save (see here).
names(l) <- names.list
lapply(names(l), function(df)
saveRDS(l[[df]], file = paste0(df, ".rds")))
list.files(pattern = ".rds")
[1] "Christmas.rds" "NewYear_Data.rds" "Thanks_giving.rds"
# To load an individual dataframe later
df <- readRDS(file = "NewYear_Data.rds")
If you want to use save, the following should work (see here; noting that save preserves variable names, hence the with statement and use of list =).
with(l,
lapply(names(l), function(df)
save(list = df, file = paste0(df, ".rda"))))
list.files(pattern = ".rda")
[1] "Christmas.rda" "NewYear_Data.rda" "Thanks_giving.rda"
Otherwise, you can save the entire list as a single file
save(l, file = "Holidays.Rda")
Working with a single list with named elements is almost always preferable to working with lots of objects in your workspace. However, two functions that may be of convenience to acheive your aims are setNames() and list2env(). The following line will create named data.frame objects in your global environment using the names in names.list...
list2env( setNames( l , names.list ) , .GlobalEnv )
setNames() is a convenience function that sets the names on an object and returns the object. list2env() assigns each element from a named list into the specified environment so you end up with 3 data.frame objects.
After running your code, we have:
> ls()
[1] "a" "A" "b" "B" "c" "C"
[7] "l" "names.list"
You can then assign the data.frames to the names in names.list:
> invisible(mapply(function(x, y) assign(x, y, envir=globalenv()), names.list, l))
> ls()
[1] "a" "A" "b" "B" "c"
[6] "C" "Christmas" "l" "names.list" "NewYear_Data"
[11] "Thanks_giving"
> Christmas
a b c
1 4 3 1
2 5 4 2
3 6 5 3
4 5 6 4
5 5 7 5
6 5 8 6
> NewYear_Data
a b c
1 1 4 3
2 2 5 4
3 3 6 5
4 4 5 6
5 5 5 7
6 6 5 8
Then, if you want to clean up your workspace and remove what you used to create the data, you can run the following (careful, this will remove EVERYTHING in your workspace, except the data frames we just created):
> rm(list=ls()[!(ls() %in% names.list)])
> ls()
[1] "Christmas" "NewYear_Data" "Thanks_giving"
Frankly, I would recommend #Andrey's answer with attach, but if you're really looking to get the data frames to be in your workspace and get rid of the stuff you used to create it, this is an option.

list of data frames from character names

I have a list of object names (character class) that I would like to convert to a list of objects in order to pass them to a loop. For example,
If I have many vectors:
subA<-c(1,2)
subB<-c(3,4)
subC<-c(9,5)
subD<-c(4,7)
I can get the names from
subnames<-ls(pattern="sub*")
> subnames
[1] "subA" "subB" "subC" "subD"
But I would like a list of the actual vectors, such as in
subvecs<-list(subA,subB,subC,subD)
> subvecs
[[1]]
[1] 1 2
[[2]]
[1] 3 4
[[3]]
[1] 9 5
[[4]]
[1] 4 7
Is there a way to do this without rewriting the whole list without quotes? It would be very time consuming with 400+ data frames. Thanks in advance.
?get is what you want
lapply(subnames, get)

Vector-list comparison in R

I am currently trying to check if a list(containing multiple vectors filled with values) is equal to a vector. Unfortunately the following functions did not worked for me: match(), any(), %in%. An example of what I am trying to achieve is given below:
Lets say:
lists=list(c(1,2,3,4),c(5,6,7,8),c(9,7))
vector=c(1,2,3,4)
answer=match(lists,vector)
When I execute this it does return False values instead of a positive result. When I compare a vector with a vector is working but when I compare a vector with a list it seems that it can not work properly.
I would use intersect, something like this :
lapply(lists,intersect,vector)
[[1]]
[1] 1 2 3 4
[[2]]
numeric(0)
[[3]]
numeric(0)
I'm not completely sure what you want the result to be (for example do you care about vector order?) but regardless you'll need to think about lapply. For example,
##Create some data
R> lists=list(c(1,2,3,4),c(5,6,7,8),c(9,7))
R> vector=c(1,2,3,4)
then we use lapply to go through each list element and apply a function. In this case, I've used the match function (since you mentioned that in your question):
R> lapply(lists, function(i) all(match(i, vector)))
[[1]]
[1] TRUE
[[2]]
[1] NA
[[3]]
[1] NA
It's probably worth converting to a vector, so
R> unlist(lapply(lists, function(i) all(match(i, vector))))
[1] TRUE NA NA
and to change NA to FALSE, something like:
m = unlist(lapply(lists, function(i) all(match(i, vector))))
m[is.na(m)] = FALSE

Resources