Save object to RData using eval(parse(text=...))) - r

I am able to write an object to a .csv file using eval(parse(text=...))) but cannot save to an .RData file. Why is that? Any suggested workarounds?
# Assign value to variable name (in my function this variable name changes)
varName <- "test"
assign(x=varName,value=mtcars)
# Check variable exists
head(test)
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
# Save .csv
write.csv(eval(parse(text = varName)), file=paste0(varName, ".csv") # works
# Save .RData
save(eval(parse(text = varName)), file=paste0(varName, ".RData")) # doesn't work
> Error in save(eval(parse(text = varName)), file = paste0(varName, ".RData")) :
object ‘eval(parse(text = varName))’ not found

The answer, aside from fortune(106) is to investigate: execute
eval(parse(text = varName))
to see what class the returned object is. Compare with what save requires.
That will show, as the other comments and answer does/did that you need a character object for that argument in save .

I think the easiest way to do this is to use
save(list = varName, file = paste0(varName, ".RData"))
It saves having to get (or mget) the variable(s), as save effectively does it for you.

Related

How to create function to use regular expressions to replace column names in a data frame?

I am feeling lost with how to create a helper function in R that takes the following 3 arguments:
a data frame,
a string pattern, and
a string "replacement pattern".
The function is supposed to replace occurrences of the string pattern in the names of the variables in the data frame with the replacement pattern.
Any guidance, tips or help would be greatly appreciated.
func <- function(x, nm1, nm2, ...) {
names(x) <- gsub(nm1, nm2, names(x), ...)
x
}
head(func(mtcars, "c", "C"))
# mpg Cyl disp hp drat wt qseC vs am gear Carb
# Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
# Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
# Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
# Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
# Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
# Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1

R: data.table fread on zip containing multiple files

What is an OS-agnostic solution to use fread on a zip? I can't seem to find one.
Setting up the stage
Let's create two dataframes, write them to disk, and put them in a zip archive (I stole this from: How to zip multiple CSV files in R?)
library(zip)
df1 <- head(mtcars)
df2 <- head(iris)
write.csv(df1, 'df1.csv')
write.csv(df2, 'df2.csv')
zip(zipfile='df.zip', files=list.files(path = getwd(), pattern = ".csv$"))
Now I want to read this zip into R
Let's say I want to read df1.csv from the zip.
fread('df.zip/df1.csv')
Error in fread("df.zip/df1.csv") : File 'df.zip/df1.csv' does not
exist or is non-readable
I tried this from fread() of file from archive
fread('unzip -p df.zip/df1.csv')
Null data.table (0 rows and 0 cols)
Warning message:
In fread("unzip -p df.zip/df1.csv") :
File '/var/folders/w5/kqy78qb17v176195dtyyc4pj40000gn/T//RtmpIlNSk8/filee1693cc7f89'
has size 0. Returning a NULL data.table.
I do not understand what it is trying to import, but clearly not my dataframe of interest.
Can you help?
Edit 1
Unzipping first is not really an option. In practice, I am working with batches of highly compressible files. Usually ~ 3000 xls files, each 1M rows. 100 Gb unzipped / 8 Gb zipped. Needless to say it would be much more comfortable to read directly from the zip!
Having unzip installed, this solution works on my computer :
fread(cmd = 'unzip -p df.zip df1.csv')
V1 mpg cyl disp hp drat wt qsec vs am gear carb
1: Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
2: Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
3: Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
4: Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
5: Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
6: Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1

Convert LIst To Dataframe Using For Loop And Saving Under Different Names In R

I am trying to convert my list consisting of 52 components to a dataframe for each of the components.
Without using the for loop will look something like this which is tedious:
df1 = as.data.frame(list[1])
df2 = as.data.frame(list[2])
df3 = as.data.frame(list[3])
.
.
.
df50 = as.data.frame(list[50])
How do I achieve this using the for loop? My attempt:
for (i in seq_along(list)) {
noquote(paste0("df", i)) = as.data.frame(list[i])
}
Error: target of assignment expands to non-language objec
I think I'll have to invovle assign.
If you have list of dataframes in list, you can name them and then use list2env to have them as separate dataframes in the environment.
names(list) <- paste0('df', seq_along(list))
list2env(list, .GlobalEnv)
Using a reproducible exmaple,
temp <- list(mtcars, mtcars)
names(temp) <- paste0('df', seq_along(temp))
list2env(temp, .GlobalEnv)
head(df1)
# mpg cyl disp hp drat wt qsec vs am gear carb
#Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
#Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
#Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
#Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
#Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
#Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
head(df2)
# mpg cyl disp hp drat wt qsec vs am gear carb
#Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
#Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
#Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
#Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
#Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
#Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
However, note that
list is an internal function in R, so it is better to name your variables something else.
As #MrFlick suggested try to keep your data in a list as lists are easier to manage rather than creating numerous objects in your global environment.
We can use assign instead of noquote from the OP's function
for (i in seq_along(list)) {
assign(paste0("df", i), value = list[[i]])
}

How to use object name in paste?

I'm trying to create a user-defined function which has as one output a network object that is named similarly to the input dataframe used in the function. Something like this.
node_attributes <- function(i){ #i is dataframe
j <- network(i)
##some other function stuff##
(i,'network',sep = '_')) <- j
}
The idea is to create add '_network' onto the i variable, which is meant to be a dataframe. So if my orignial dataframe is foo_bar_data, my output would be: foo_bar_data_network.
It is possible to get the name of input variables with deparse(substitute(argname)).
func <- function(x){
depsrse(substitute(x))
}
func(some_object)
## [1] "some_object"
I am not completely sure how you want to use the name of the input, so I used something similar to the answer of #JackStat
node_attributes <- function(i){
output_name <- paste(deparse(substitute(i)), 'network', sep = '_')
## I simplified this since I don't know what the function network is
j <- i
assign(output_name, j, envir = parent.frame())
}
node_attributes(mtcars)
head(mtcars_network)
## mpg cyl disp hp drat wt qsec vs am gear carb
## Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
## Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
## Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
## Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
## Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
## Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1
That said I don't really see any reason to code like this. Normally, returning the output from the function is the recommended way.
you can use assign
j <- network(i)
assign(paste0(i,'network',sep = '_'), j)

Get data frame from character variable

I pass data frame name as string into a function. How do I get content of referenced data frame from the string? Suppose I have string 'mtcars' and I want to print data frame mtcars:
printdf <- function(dataframe) {
print(dataframe)
}
printdf('mtcars');
I think you'll need a get in there if the input is a string. Also, depending on your usage of the function, the explicit print might not be necessary:
printdf <- function(dataframe) {
get(dataframe)
# print(get(dataframe))
}
head(printdf("mtcars"))
# mpg cyl disp hp drat wt qsec vs am gear carb
# Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
# Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
# Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
# Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
# Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
# Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1

Resources