I am trying to automate the naming of a ggplot output saved using ggsave()
When I create the following plot I am able to retrieve the name of the plot using a combination of the deparse and substitute functions if I state the plot name explicitly
# make the plot
df <- data.frame(x = 1:10, y = 1:10)
my_plot <- ggplot(df, aes(x, y))+geom_point()
# generate the file name
filename <- paste0(deparse(substitute(my_plot)), ".jpg")
filename
However, I am trying to pass the plot name to the substitute function directly using without having to state it twice using .Last.value. This generates the incorrect result.
my_plot_name <- deparse(substitute(.Last.value))
my_plot_name
## [1] ".Last.value"
How can I access the name of the last ggplot object (or any other object) to be saved without stating the name explicitly?
EDIT: To be specific, my desired output based on the above example and some pseudo code would look like this:
filename <- paste0(deparse(substitute(.Last.value)), ".jpg")
filename
## [1] "my_plot.jpg"
You should be able to get it directly from the filename you're creating:
my_plot_name <- tools::file_path_sans_ext(filename)
my_plot_name
## [1] "my_plot"
Updated after edits:
.Last.value will only store the value, not the name of the variable that the value is being assigned into. First idea I'd have otherwise would be to check the names of variables in the environment to find which is equal to .Last.value. It seems to work in this simple case of your example:
my_plot <- ggplot(df, aes(x, y))+geom_point()
filename <- paste0(Filter(function(i) identical(get(i), .Last.value), ls()), ".jpg")
filename
## [1] "my_plot.jpg"
Related
I wanna save a list of scatterplots with their filenames.
Therefor I give each plot a name, which worked perfectly:
names(scatterplot_standardcurve) <-
sub("\\.xlsx$",
".png",
names(standardcurve_concentration))
> print(scatterplot_standardcurve)
$K_20210722
$A_20210722
$c_20210722
$d_20210722
$t_20210722
$v_20210722
And then I want to save them in a specific folder but I always get an error
lapply(names(scatterplot_standardcurve),
function(nm) print(scatterplot_standardcurve[[nm]]) +
ggsave(filename = file.path("Z:/output/scatterplot_standardcurve/",
nm )))
Error: Unknown graphics device ''
Using imap you'll be able to iterate over the ggplot object as well as it's name. Try -
library(purrr)
library(ggplot2)
imap(scatterplot_standardcurve,
~ggsave(sprintf("Z:/output/scatterplot_standardcurve/%s.png", .y), .x))
I generate a bunch of graphs and write them into a list variable, something like the following.
graphsListHolder <- list()
loop around the following code for as many plots as I make
filename <- paste some elements together to create a unique name
graphsListHolder[[filename]] <- p # p is the name of the ggplot plot
I save graphsListHolder as a .rds file.
Later I want to read in the res file, choose from plots in the graphsListHolder file and display with grid.arrange. I can hardcode the plot number and the following example works fine when run, plotting two graphs, one on top of the other.
grid.arrange(
graphsListHolder[[3]], graphsListHolder[[5]]
)
But if I construct a character variable temp like this (or variations on this)
temp <- "graphsListHolder[[3]], graphsListHolder[[5]]"
and change the grid.arrange code to
grid.arrange(
temp
)
I get
Error in gList(list("graphsListHolder[[3]], graphsListHolder[[5]]", wrapvp = list( :
only 'grobs' allowed in "gList"
In addition: Warning message:
In grob$wrapvp <- vp : Coercing LHS to a list
I also tried eval(parse(text = temp) without success.
I'm not sure how you want to choose them, but say you had a vector of the elements you wanted
x <- c(3,5)
Then you could do
grid.arrange(grobs=graphsListHolder[x])
Trying to turn arbitrary strings into executable code usually isn't a good idea. Often there are more "traditional" alternatives in R.
For example
graphsListHolder<-Map(function(x) {
ggplot(data.frame(x=1:10, y=x*1:10)) + geom_point(aes(x,y)) + ggtitle(x)}, 1:5)
x <- c(3,5)
grid.arrange(grobs=graphsListHolder[x])
I want to make an R script to produce a simple scatter plot, passing the columns to plot as a parameter.
This is what I'm doing now:
ds <- read.csv("filename", sep=";")
args<-commandArgs(TRUE)
x <- args[1]
y <- args[2]
output <- args[3]
png(output)
plot(ds$x, ds$y)
dev.off()
Then I launch the script this way:
Rscript myscript.R arg1 arg2 output.png,
but I get the execution halted because it can't fetch any data.
If I use the correct column name in the plot function (having read the column header offline), it works well of course.
If I ask for typeof(ds$x) I get NULL, so the problem seems to be the args are not of the correct type; what am I doing wrong?
ds$y and ds$x will not work in this form because x and y are characters.
If you try on your console:
x <- 'arg1'
> ds$x
NULL
You will see it will not work and will return NULL.
Therefore try this:
ds <- read.csv("filename", sep=";")
args<-commandArgs(TRUE)
x <- args[1]
y <- args[2]
output <- args[3]
png(output)
plot(ds[,x], ds[,y])
dev.off()
You're correct, the problem is with the type of x and y. Add
cat(class(x),"\n")
to your script and you see that the type of x is character. So change the call to plot to
plot(get(x,ds),get(y,ds))
and it works.
I am trying to make a script to allows user to decide what column will be chosen for the graph (slope, r - value, p - value, ect.). However I am having trouble. I know that when I read it in, the data type is a string. How do i convert it to a compatible type so I can use it as a column name? Here is an example of the script:
print("State the file name (include .csv)")
filename <- readline()
file <- read.csv(filename)
print("State the variable to be plotted")
var <- readline()
hist(file$var)
Use
y = data[, "colname"]
to extract 'colname' variable into a vector y (Don't forget the comma).
Or you can use
y = data[["colname"]]
Or even using backtick quotes
col.name = "colname"
y = data[`col.name`]
Your code:
filename = readline()
data = read.csv(filename)
colname = readline()
hist(data[, colname])
I'm using R to loop through a data frame, perform a calculation and to make a plot.
for(i in 2 : 15){
# get data
dataframe[,i]
# do analysis
# make plot
a <- plot()
}
Is there a way that I can make the plot object name 'a', using the value of 'i'? For example, a + "i" <- plot(). Then I want to add that to a vector so I have a series of plots that I can then use at a later stage when I want to make a pdf. Or perhaps there is another way of storing this.
I'm familiar with the paste() function but I haven't figured out how to define an object using it.
If you want a "vector" of plot objects, the easiest way is probably to store them in a list. Use paste() to create a name for your plot and then add it to the list:
# Create a list to hold the plot objects.
pltList <- list()
for( i in 2:15 ){
# Get data, perform analysis, ect.
# Create plot name.
pltName <- paste( 'a', i, sep = '' )
# Store a plot in the list using the name as an index.
# Note that the plotting function used must return an *object*.
# Functions from the `graphics` package, such as `plot`, do not return objects.
pltList[[ pltName ]] <- some_plotting_function()
}
If you didn't want to store the plots in a list and literally wanted to create a new object that had the name contained in pltName, then you could use assign():
# Use assign to create a new object in the Global Environment
# that gets it's name from the value of pltName and it's contents
# from the results of plot()
assign( pltName, plot(), envir = .GlobalEnv )
Have a look at the packages lattice or ggplot2, the plot functions in these packages create objects which can be assigned to variables and can be printed or plotted at a later stage.
For instance with lattice:
library("lattice")
i <- 1
assign(sprintf("a%d", i), xyplot(1:10 ~ 1:10))
print(a1) # you have to "print" or "plot" the objects explicitly
Or append the objects to a list:
p <- list()
p[[1]] <- xyplot(...)
p[[2]] <- xyplot(...)