Create an unique pdf with a FOR loop [duplicate] - r

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

Related

Any way to access the plot object generated by DescTools::Desc()?

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)

Efficient way to review formulas that generate named objects in R

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

(wx)Maxima plot point by point, numbered

I have a list of roots and I want to plot the real/imaginary parts. If s=allroots(), r=realpart() and i=imagpart(), all with makelist(). Since length(s) can get ...lengthy, is there a way to plot point by point and have them numbered? Actually, the numbering part is what concerns me most. I can simply use points(r,i) and get the job done, but I'd like to know their occurence before and after some sorting algorithms. It's not always necessary to plot all the points, I can plot up until some number, but I do have to be able to see their order of having been sorted out.
I have tried multiplot_mode but it doesn't work:
multiplot_mode(wxt)$
for i:1 thru length(s) do draw2d(points([r[i]],[i[i]]))$
multiplot_mode(none)$
All I get is a single point. Now, if this should work, using draw2d's label(["label",posx,posy]) is very handy, but can I somehow evaluate i in the for loop inside the ""?
Or, is there any other way to do it? With Octave? or Scilab? I'm on Linux, btw.
Just to be clear, here's what I currently do: (I can't post images, here's the link: i.stack.imgur.com/hNYZF.png )
...and here is the wxMaxima code:
ptest:sortd(pp2); length(ptest);
draw2d(proportional_axes=xy,xrange=[sort(realpart(s))[1]-0.1,sort(realpart(s))[length(s)]+0.1],
yrange=[sort(imagpart(s))[1]-0.1,sort(imagpart(s))[length(s)]+0.1],point_type=0,
label(["1",realpart(ptest[1]),imagpart(ptest[1])]),points([realpart(ptest[1])],[imagpart(ptest[1])]),
label(["2",realpart(ptest[2]),imagpart(ptest[2])]),points([realpart(ptest[2])],[imagpart(ptest[2])]),
label(["3",realpart(ptest[3]),imagpart(ptest[3])]),points([realpart(ptest[3])],[imagpart(ptest[3])]),
label(["4",realpart(ptest[4]),imagpart(ptest[4])]),points([realpart(ptest[4])],[imagpart(ptest[4])]),
label(["5",realpart(ptest[5]),imagpart(ptest[5])]),points([realpart(ptest[5])],[imagpart(ptest[5])]),
label(["6",realpart(ptest[6]),imagpart(ptest[6])]),points([realpart(ptest[6])],[imagpart(ptest[6])]),
label(["7",realpart(ptest[7]),imagpart(ptest[7])]),points([realpart(ptest[7])],[imagpart(ptest[7])]),
label(["8",realpart(ptest[8]),imagpart(ptest[8])]),points([realpart(ptest[8])],[imagpart(ptest[8])]),
label(["9",realpart(ptest[9]),imagpart(ptest[9])]),points([realpart(ptest[9])],[imagpart(ptest[9])]),
label(["10",realpart(ptest[10]),imagpart(ptest[10])]),points([realpart(ptest[10])],[imagpart(ptest[10])]),
label(["11",realpart(ptest[11]),imagpart(ptest[11])]),points([realpart(ptest[11])],[imagpart(ptest[11])]),
label(["12",realpart(ptest[12]),imagpart(ptest[12])]),points([realpart(ptest[12])],[imagpart(ptest[12])]),/*
label(["13",realpart(ptest[13]),imagpart(ptest[13])]),points([realpart(ptest[13])],[imagpart(ptest[13])]),
label(["14",realpart(ptest[14]),imagpart(ptest[14])]),points([realpart(ptest[14])],[imagpart(ptest[14])]),*/
color=red,point_type=circle,point_size=3,points_joined=false,points(realpart(pp2),imagpart(pp2)),points_joined=false,
color=black,key="",line_type=dots,nticks=50,polar(1,t,0,2*%pi) )$
This is for 14 zeroes, only. For higher orders it would be very painful.
I gather that the problem is that you want to automatically construct all the points([realpart(...), imagpart(...)]). My advice is to construct the list of points expressions via makelist, then append that list to any other plotting arguments, then apply the plotting function to the appended list. Something like:
my_labels_and_points :
apply (append,
makelist ([label ([sconcat (i), realpart (ptest[i]), imagpart (ptest[i])]),
points ([realpart (ptest[i])], [imagpart (ptest[i])])],
i, 1, length (ptest)));
all_plot_args : append ([proptional_axes=..., ...], my_labels_and_points, [color=..., key=..., ...]);
apply (draw2d, all_plot_args);
The general idea is to build up the list of plotting arguments and then apply the plotting function to that.

The function doesn't return a list and Sage doesn't plot it

I've got the function f(x,y) and I want to iterate it a number of times and plot the resulting points. What I've done is:
def orbita(p,n):
a = [p]
for i in range(n-1):
p = f(p[0],p[1])
a.append(p)
print a
When applied to the point p = (1,2) and asked for n = 5 iterations, this function returns the following:
[(1, 2), (2, 5/2), (5/2, 29/20), (29/20, 1241/1450), (1241/1450, 7285162/5218405)]
Which is correct. However, when I try to plot this list of points by point(orbita((1,2),5)), I simply get an empty plot.
At first I thought that this was an issue with the fact that point() plots "either a single point (as a tuple), a list of points, a single complex number, or a list of complex numbers", quoted from here, because I checked type(orbita((1,2),5)) and got NoneType. However, when I tried to assign the list to a variable by L = orbit((1,2),5) my variable is empty, since typing L returns nothing, so I'm not sure anymore if that is the problem. If I copy the list and write:
point([(1, 2), (2, 5/2), (5/2, 29/20), (29/20, 1241/1450), (1241/1450, 7285162/5218405)])
The plot works perfectly, but I would like to use this function for plotting at least a couple of hundred points, so I wouldn't like to copy them every time. I'm new with both Sage and Python, so I really don't know what I'm doing wrong at any level.
How can I print the outcome of the function orbita(p,n) or how can I modify it so that by typing point(orbita(p,n)) I obtain a plot?
Here is your problem.
this function returns the following:
No, it doesn't. It prints the following. As you correctly identify, it returns None. So you have to have it return the list of tuples. It looks like you are plenty experienced in Python to figure out how to do that, so I won't include the details, but please do follow up if you still have trouble.

Graphing distribution of independent variable for any given dataset

I am looking to automate the process of exploratory data analysis and would like to graph the distribution (using line plots, histograms, density curves, etc.) of all the input variables. As my code stands, I am simply getting 4 blank graphics windows. What am I doing incorrectly? If there is a better approach, I am open to that as well.
mydata <- read.csv("http://www.ats.ucla.edu/stat/data/binary.csv")
for (i in names(mydata)){
qplot(data=mydata,i,geom="bar", fill="admit")
dev.new()
}
This situation looks like one where aes_string would come in handy (along with the addition of print around your call to ggplot). I found this post showing how to use aes_string with ggplot inside a loop.
So it would look something like this:
mydata$admit = factor(mydata$admit)
for(i in names(mydata)) {
print(ggplot(mydata) + geom_bar(aes_string(x = i, fill = "admit")))
}
I'm working in RStudio so have skipped the dev.new part of your code. I found I needed to convert admit to a factor, as well.

Resources