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.
Related
I'm trying to run some PS cmdlets in R with system2 but I cannot find a way of outputting the result into an R data frame.
Example:
PSCommand_ConnectToMSOL <- "Connect-MsolService"
PSCommand_GetAllLicensingPlans <- "Get-MsolAccountSku | ft SkuPartNumber, ActiveUnits, ConsumedUnits"
PS_output <- system2("powershell", args = PSCommand_ConnectToMSOL, PSCommand_GetAllLicensingPlans)
PS_output
The result in PowerShell is:
However in R studio I don't see a result:
How can I output the results to a data frame?
You have a typo/incorrect syntax in your code. Per the system2 documentation, the args argument takes in a character vector (i.e. character()):
Change:
PS_output <- system2("powershell", args = PSCommand_ConnectToMSOL, PSCommand_GetAllLicensingPlans)
to
PS_output <- system2("powershell", args = c(PSCommand_ConnectToMSOL, PSCommand_GetAllLicensingPlans))
With the original code you posted the PSCommand_GetAllLicensingPlans variable would be passed onto the stdout system2 argument which wouldn't make any sense..
Maybe try examining your code just a smidge more before looking for outside help next time!
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"
I have a lot of plots named "plt_xxxx" and I would like to plot all of them in a loop.
I tried this code but it did not work. When I run the code nothing happens, no error.
pltEnv <- ls()[grepl("plt_", ls())]
for(x in pltEnv){
get(x)
}
When I run this code it works:
get(pltEnv[1])
get(pltEnv[2])
# ...
You can use:
plt_1 <- plotly::plot_ly(x=1, y = 1)
plot_names <- ls(pattern = "plt_.*")
eval(parse(text = plot_names[1]))
I would save my plot in a named list instead to access them later.
It worked when I ran mget(pltEnv)
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 have written an executable script in R that will simply plot a graph given an input file in a tab delimited format. However, the script I wrote is specific to a single file in terms of what to use as x and y. I want to have this script be able to plot whatever file I give it. All files I will be using for this script will be in the same format: Tab delimited with 4 headers with labels a, b, c, d. Labels b,c, and d have a different name for each file. My x values for the graph will be the values under header b and y values for the graph will be the values under header c. How can I plot a graph that will use whatever is under header b and c?
My script is posted below.
#!/usr/bin/env Rscript
args = commandArgs(trailingOnly=TRUE)
data = read.table((args[1]), header=TRUE, fill=TRUE, sep="\t")
attach (data)
jpeg(args[2])
plot (RPMb, RPMc)
dev.off()
Instead of using attach() (which is almost never recommended), use data frame indexing to extract the relevant variables from your data variable.
#!/usr/bin/env Rscript
args = commandArgs(trailingOnly=TRUE)
data = read.table((args[1]), header=TRUE, fill=TRUE, sep="\t")
jpeg(args[2])
x <- names(data)[2]
y <- names(data)[3]
plot (data[[x]], data[[y]],xlab=x,ylab=y)
dev.off()
You could also just use plot(data[,2],data[,3]) ...
A couple of other details/comments:
it's generally best to avoid naming variables for built-in functions such as data. It will usually work, but occasionally it will bite you.
are you sure you want JPEG output? Either PNG or PDF are usually best for line graphs, depending on whether you need a raster or a vector format ...