How to convert a matrix to dictionary like a list? - r

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"]

Related

Efficient way of assigning attribute table names based on a partial list element name

I have a list with path names as the element names in list l1.
# File List
l1 <- list(2,3,4,5)
names(l1) <- c("C:/Users/2013_mean.csv",
"C:/Users/2013_median.csv",
"C:/Users/2015_mean.csv",
"C:/Users/2015_median.csv")
I would like to assign a attribute table to the list that looks similar to the following in a more efficient manner. I would like to extract only a portion of the path name from the elements in l1 assign them to its respective componenent. For example:
I would like to "grab" the name "2013_mean" from "C:/Users/2013_mean.csv" in l1 and assign it to that element in the attribute table. Is there a more efficient way of doing this?
attributes(l1) <- data.frame(id = c("2013_mean", "2013_median", "2015_mean", "2015_median")
)
attributes(l1)
We can use basename on the names of the list to extract the substring
attributes(l1) <- data.frame(id = sub("\\.csv", "", basename(names(l1))))
-output
> l1
[[1]]
[1] 2
[[2]]
[1] 3
[[3]]
[1] 4
[[4]]
[1] 5
attr(,"id")
[1] "2013_mean" "2013_median" "2015_mean" "2015_median"
Or another option is basename + file_path_sans_ext
tools::file_path_sans_ext(basename(names(l1)))
[1] "2013_mean" "2013_median" "2015_mean" "2015_median"

How to create a R dictionary [duplicate]

I want to make the equivalent of a python dict in R. Basically in python, I have:
visited = {}
if atom_count not in visited:
Do stuff
visited[atom_count] = 1
The idea is, if I saw that specific, atom_count, I have visited[atom_count] = 1. Thus, if I see that atom_count again, then I don't "Do Stuff". Atom_Count is an integer.
Thanks!
The closest thing to a python dict in R is simply a list. Like most R data types, lists can have a names attribute that can allow lists to act like a set of name-value pairs:
> l <- list(a = 1,b = "foo",c = 1:5)
> l
$a
[1] 1
$b
[1] "foo"
$c
[1] 1 2 3 4 5
> l[['c']]
[1] 1 2 3 4 5
> l[['b']]
[1] "foo"
Now for the usual disclaimer: they are not exactly the same; there will be differences. So you will be inviting disappointment to try to literally use lists exactly the way you might use a dict in python.
If, like in your case, you just want your "dictionary" to store values of the same type, you can simply use a vector, and name each element.
> l <- c(a = 1, b = 7, f = 2)
> l
a b f
1 7 2
If you want to access the "keys", use names.
> names(l)
[1] "a" "b" "f"
I believe that the use of a hash table (creating a new environment) may be the solution to your problem. I'd type out how to do this but I just did so yesterday day at talkstats.com.
If your dictionary is large and only two columns then this may be the way to go. Here's the link to the talkstats thread with sample R code:
HASH TABLE LINK

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 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)

Resources