list of data frames from character names - r

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)

Related

lapply on a list of list not working in R

I have
typeof(A)
>"list"
typeof(A[1])
>"list"
typeof(A[[1]])
>"double"
And when I run
A=lapply(A,unlist)
typeof(A[1])
>"list"
The result seems to be the same. Yet if I run
B=unlist(A[1])
typeof(B)
"double"
Please help me understand this behaviour. Why is there a difference between the two? Should lapply not apply the function to each element of the list? Than A[i] should be like B?
lapply actually returns a list as its output. It applies a function to several elements, and returns each output as an element of a list.
For what it's worth, A[[1]] being of type double actually tells you you have a list of doubles. The [[ ]] references elements of a list, the [] references elements of a vector. So by asking for A[1] you're getting the first element as a list, by asking for A[[1]] you're getting the first element de-listed.
I suspect what you want is just unlist(A). That will return each element of A as an element in a single vector. In your case A is a list of doubles. So hopefully that's what you want.
Take this example
test = list(list(5), list(3), list(1))
> test #Notice this is a list of lists, each containing one element
[[1]]
[[1]][[1]]
[1] 5
[[2]]
[[2]][[1]]
[1] 3
[[3]]
[[3]][[1]]
[1] 1
> test[2] #Notice this has exported the second element as a new list with one element
[[1]]
[[1]][[1]]
[1] 3
> test[[2]] #Notice this has exported the second element not as a list, so now we have one listed instead of two nested lists.
[[1]]
[1] 3
lapply(test, unlist) #This returns a list of element rather than a list of lists
[[1]]
[1] 5
[[2]]
[1] 3
[[3]]
[1] 1
unlist(lapply(test, unlist)) #This returns a vector of elements by unlisting the list of elements we created in the previous step
[1] 5 3 1
I hope that clears up some of the behaviour :)

Creating named list of large set of data frames 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 ...

R: return column using get() and paste()

Why does get() in combination with paste() work for dataframes but not for columns within a dataframe? how can I make it work?
ab<-12
get(paste("a","b",sep=""))
# gives: [1] 12
ab<-data.frame(a=1:3,b=3:5)
ab$a
#gives: [1] 1 2 3
get(paste("a","b",sep=""))
# gives the whole dataframe
get(paste("ab$","a",sep=""))
# gives: Error in get(paste("ab$", "a", sep = "")) : object 'ab$a' not found
Columns in dataframes are not first class objects. Their "names" are really indexing values for list-extraction. Despite the understandable confusion caused by the existence of the names function, they are not true R-names, i.e. unquoted tokens or symbols, in the list of R objects. See the ?is.symbol help page. The get function takes a character value, and then looks for it in the workspace and returns it for further processing.
> ab<-data.frame(a=1:3,b=3:5)
> ab$a
[1] 1 2 3
> get(paste("a","b",sep=""))
a b
1 1 3
2 2 4
3 3 5
>
> # and this would be the way to get the 'a' column of the ab object
get(paste("ab",sep=""))[['a']]
If there were a named object target with a value "a" tehn you could also do:
target <- "a"
get(paste("ab",sep=""))[[target]] # notice no quotes around target
# because `target` is a _real_ R name
It doesn't work because get() interprets the string it's passed as referring to an object named "ab$a" (not as referring to the element named "a" of the object named "ab") . Here's probably the best way to see what that means:
ab<-data.frame(a=1:3,b=3:5)
`ab$a` <- letters[1:3]
get("ab$a")
# [1] "a" "b" "c"

How to convert a matrix to dictionary like a list?

I have a matrix like:
> mat
name path
1 A A.csv
2 B B.csv
3 C C.csv
and I want to convert it to dictionary-like list as:
> list("A"="A.csv", "B"="B.csv", "C"="C.csv")
$A
[1] "A.csv"
$B
[1] "B.csv"
$C
[1] "C.csv"
I'd appreciate if anyone let me know how to do this.
Pretty simple, just use as.list to convert the second column to a list and then set the names with names
l <- as.list(mat[,"path"])
names(l)<-mat[,"name"]

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.

Resources