I am using Desc() from DescTools to describe some variables in a rmarkdown PDF document. The problem is that it generates 3 plots that are kept in line when I knit the document, thus clipping the images.
Example:
dates <- sample(seq(as.Date('1999/01/01'), as.Date('2021/01/01'), by="day"), 1000)
results <- DescTools::Desc(dates)
results
The output contains 3 plots. I can find the individual responses using the list in results[[1]]], but I can't find the plot objects, which I think could be a way to put then one below the other.
Any thoughts?
There are no plot objects in results.
Instead, when you type results in your console, it invokes the S3 generic print, which in turn dispatches the print.Desc method. By default, print.Desc will call a plotting function based on the "class" member of results, which in your example is "Date". If you type DescTools:::plot.Desc.Date in your console, you will see the function that actually generates the plot every time you print results.
So there are no plot objects. There is data to create a plot, and whenever you print results to the console, the plots are created by a call to a plotting function.
The Desc plotting functions seem to have very few options available to allow modifications, so the best option would probably be to use the data inside results to create your own plots. If you wish to see the contents of results without the plots, simply type:
print(results, plotit = FALSE)
And if you want the three plots one at a time, you can do:
DescTools:::plot.Desc.Date(results[[1]], type = 1)
DescTools:::plot.Desc.Date(results[[1]], type = 2)
DescTools:::plot.Desc.Date(results[[1]], type = 3)
Related
I am making a function call in R. The function returns a list and in it has a call to plot(). From this one call, I need to record the plot as an object and store the list as a separate object. I need to store the plot because I later give it to ggarrange() along with other plots. I must store both outputs in one call of the function because the function runs permutations. As a result, it will produce a slightly different output each time. Therefore, in order for the data in the list to match the plot, the call can only be made once.
The line of code below is what I am currently using that successfully stores the plot as ggplot object. It does not store the list.
my_plot <- as.ggplot(~(my_function(input1,input2, permutations=1000)))
The code below will return the list, but not save the plot.
my_list <- my_function(input1,input2, permutations=1000)
Does anyone know a way of accomplishing what I am trying to do?
If I have a named object (in my case a named plot) in R, is there an efficient way to double check the formula that generated it? As of now I am scrolling back through the console, but I'm hoping that there is a more efficient way.
For example, at the start of my project I input
Boxplot <- ggplot(plotting input) + geom_boxplot(plotting input)
Now I can call Boxplot by name to plot it, but I want to be able to efficiently review my ggplot input. Is there a tool to do this?
For your example, you can see the elements of Boxplot using:
names(Boxplot)
So you can see, for example, the input data using:
Boxplot$data
Or the parameters and type of the plot using:
Boxplot$layers
TL;DR: I'm getting the above (and below) error. How do I fix it?
Since I'm relatively new to R, this has me stumped. I'm trying to create an xyplot where both the axes are log-transformed. I've gotten this far:
library(lattice)
xyplot(`APC-H7-A`~`PE-Cy5-A`,lymphocytes, smooth=FALSE,
xlim=c(-100,10000), ylim=c(-100,10000),
scales=list(x=list(log=10),y=list(log=10)))
And I keep getting an error:
Error in Math.factor(x, xbase) : ‘log’ not meaningful for factors
I'm guessing that the error means something in my code isn't recognised as a number? but I don't really know where to start looking.
Lymphocytes is an object of flowFrame class, within the flowCore package:
Description. This class represents the data contained in a FCS file or similar data structure. There are three parts of the data:*
A numeric matrix of the raw measurement values with rows=events and columns=parameters
Annotation for the parameters (e.g. the measurement channels, stains, dynamic range)
Additional annotation provided through keywords in the FCS file*
This is a complex data structure and it is not straightforward to access the raw data. The manual page of flowFrame (see help(flowFrame)) says that we can index this object, and with the exprs method is the way to the raw data. Also this class has its own plotting methods, I assume you have a good reason why you choose lattice instead. With loading the example data the way below I could run your plotting code:
require(flowCore)
require(lattice)
data(GvHD)
xyplot(exprs(GvHD[[1]][, "FL4-H"]) ~ exprs(GvHD[[1]][, "FL2-H"]),
smooth=FALSE,
xlim=c(-100,10000),
ylim=c(-100,10000),
scales=list(x=list(log=10),
y=list(log=10)),
xlab = "FL2-H",
ylab = "FL4-H")
I don't know what is FL2-H, FL4-H and index 1 in this data array, but I am sure you will find out quickly as you know your data.
I'm trying to write a function that plots a ggplot facet_wrap plot over multiple pages. It's just a hack, as this feature seems to be on the ggplot2 feature to-do list. I do some small calculations to find the number of pages I'm going to need, the number of rows of my data.frame that I need per page etc. I'm pretty confident this all works.
pdf(filename)
for (i in seq(num_pages)){
slice = seq(((i-1)*num_rows)+1,(i*num_rows))
slice = slice[!(slice > nrow(df.merged))]
df.segment=df.merged[slice,]
p <- ggplot(df.segment, aes(y=mean,x=phenotype))
p <- p + geom_bar(stat="identity",fill="white",colour="black")
p + facet_wrap("ID",scales="free_y",ncol=n_facets,nrow=n_facets)
}
dev.off()
My problem is that, by wrapping it all up in a for loop like this, in between the pdf() and dev.off() functions, is that the for loop doesn't seem to wait for ggplot to do its thing, and blazes through its loop very quickly and outputs an invalid PDF.
If I set i = 1, start the pdf(), run the above code inside the for loop, then set i=2, then run the code, and so on until I get bored (i=3) then turn off the device the resulting PDF is brilliant.
Is there a way I can get the for loop to wait for the final line to finish plotting before moving onto the next iteration?
I think the problem is that you need print() around your last line (p+ ...) to get it to actually print to the device inside the for loop . . .
Exactly. Page 39 of the ggplot2 book tells us that when you create ggplot2 objects, you can "Render it on screen, with print(). This happens automatically when running interactively, but inside a loop or function, you'll need to print() it yourself".
Running the R script
list1<-list()
list2<-list()
for(i in 1:3){
list1[[i]]<-i
}
for(i in 1:3){
list2[[i]]<-qplot(i)
}
I recognize that list1 contains the elements 1,2,3. But list2 contains three times the element qplot(3).
Is qplot not compatible with looping? How can I save my plots in a list using a loop?
In ggplot the aesthetics are stored as expressions and evaluated when the plot is rendered. So qplot(i) does not generate a plot, but rather a plot definition, using a reference to the variable i. All three plots are the same in the sense that they all reference i.
If you type
list2[[1]]
after the second loop has run, you cause the ggplot object stored in list2[[1]] to be rendered, using whatever value i is set to at the moment (which is 3 after the loop).
Try this:
i <- 4
list2[[1]]
Now the plot rendered is equivalent to qplot(4).
The workaround depends on what you are trying to achieve. The basic idea is not to use external variables in aesthetics. So in your trivial case,
for(i in 1:3){
list2[[i]]<-ggplot(data.frame(x=i), aes(x))+geom_histogram()
}
will work. This is because the reference to the external variable i is not in the aesthetics (e.g., the call to aes(...).