Loop through a series of qplots
As the other answers have said, wrap each qplot()
call in print()
(this is R FAQ 7.22). The reason why is that ggplot's aren't printed to the graphics device until print.ggplot
is called on them. print()
is a generic function that dispatches to print.ggplot
behind the scenes.
When you are working in the repl ("read-evaluate-print loop", aka shell) the return value of the previous input line is automatically printed via an implicit call to print()
. That's why qplot(mtcars[,Var], wt, data=mtcars, xlab=Var)
is working for you. It's nothing to do with scope or the for loop. If you were to put that line anywhere else that isn't directly returning to the repl, such as in a function that returns something else, it would do nothing.
Loop multiple qplot in same graph
It's easier to use "long" data rather than "wide" data with ggplot2 (see here). This means the first thing to do is get your data into the right format:
library(reshape2)
myData$Time = time
data.melted = melt(myData, id="Time")
This turns it into a format more like:
Time variable value
1 Crude Oil 18.54
2 Crude Oil 17.40
At that point, it's easy to make this kind of plot with facetting (no for loop necessary):
print(ggplot(data.melted, aes(x=time, y=value)) + geom_line() + facet_wrap(~ variable)
+ theme_bw())
qplot Break Formating in a loop
There are a few strange things in your code, and I'm not sure which is causing your problem, but here's a working equivalent:
for(i in unique(cdata$temp)) {
cdata_i <- cdata[cdata$temp == i, ]
my.plot <- ggplot(cdata_i, aes(x = Year, y = Consumption)) +
geom_point() +
labs(x = "Year",
y = "Consumption (kcal)",
title = paste("Consumption:", prettyNum(i, ","))) +
scale_x_continuous(breaks = seq(2010, 2100, by = 10))
print(my.plot)
}
A few suggestions:
- Don't overwrite
i
within the loop -i
is useful (I use it to make the titles below) - Use the function
ggplot
instead ofqplot
.qplot
is fine for quick, interactive plots, but as soon as you're trying to do something more complex (like this), usingggplot
will save you a lot of headaches. - Use the
limits
argument ofscale_x_continuous
to make sure that your plots all have the samex
axis. Settingbreaks
alone won't guarantee that 2010 and 2100 appear on every plot.
qplot call overwrites list elements
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(...)
.
I have a for loop of qplots, how can you structure the plots individually using LaTeX code e.g adding captions to the plots
\documentclass{article}
\begin{document}
<<echo = FALSE, fig.cap = c("First, Second, Third"), results = "asis">>=
library(ggplot2)
for (i in 1:3) {
print(qplot(x = 1, y = i))
cat("Arbitrary \\LaTeX code! \\clearpage")
}
@
\end{document}
You can use the chunk option fig.cap
to add captions to your plots. Note that this will wrap your figure in a figure
environment, turning it into a float.
Use the chunk option results="asis"
to be able to print arbitrary text (including LaTeX markup) into your document using cat()
.
Looping cut2 color argument in qplot
Your desired output is easier to achieve using ggplot()
instead of qplot()
, since you can use aes_string()
, that accepts strings as arguments.
plotCols <- function(x) {
cols <- names(x)
for (i in 1:length(cols)) {
assign(paste0("cutEx", i), cut2(x[, i]))
p <- ggplot(x) +
aes_string("index", "CompressiveStrength", color = paste0("cutEx", i)) +
geom_point()
print(p)
}
}
plotCols(training)
Loop through and plot columns of two identical dataframes
As you suggest, I would indeed first rearrange into a list of plottable data frames before calling the plot command. I think that would especially be the way to go if you want to feed the data
argument into ggplot
. Something like:
plot_dfs <- lapply(names(df1),function(nm)data.frame(col1 = df1[,nm], col2 = df2[,nm]))
for (df in plot_dfs)plot(x = df[,"col1"], y = df[,"col2"])
or using ggplot:
for (df in plot_dfs){
print(
ggplot(data = df, aes(x=col1, y=col2)) +
geom_point())}
and if you want to add the column names as plot titles, you can do:
for (idx in seq_along(plot_dfs)){
print(
ggplot(data = plot_dfs[[idx]], aes(x=col1, y=col2)) +
ggtitle(names(df1)[idx]) +
geom_point())}
How do I plot more than one series using qplot?
I Hope this helps
gplot2 works best with data in long format, like so:
Year score sd variable
1 1950 10 1.1 bus
2 1960 20 2.2 bus
3 1970 30 3.3 bus
4 1980 40 4.4 bus
5 1950 20 1.1 car
6 1960 20 2.2 car
7 1970 40 3.3 car
8 1980 40 4.4 car
This will get the data into R:
data <- structure(list(Year = structure(c(1L, 2L, 3L, 4L, 1L, 2L, 3L,
4L), class = "factor", .Label = c("1950", "1960", "1970", "1980"
)), score = c(10, 20, 30, 40, 20, 20, 40, 40), sd = c(1.1, 2.2,
3.3, 4.4, 1.1, 2.2, 3.3, 4.4), variable = c("bus", "bus", "bus",
"bus", "car", "car", "car", "car")), .Names = c("Year", "score",
"sd", "variable"), row.names = c(NA, -8L), class = "data.frame")
And this will make the plot, with dodge an all. You properbly need the dodge, because your data is overlapping. You can control the amount of dodging with the "W" value.
ggplot(data, aes(x=Year, y=score,col=variable))+
geom_point(position=position_dodge(w=0.2))+
geom_pointrange(aes(ymin=score-sd, ymax=score+sd,group=Year),position=position_dodge(w=0.2))
Background picture and loop over qplot, how can I only update the date without reprinting the rest
One way to stop the flashing is to prevent the screen from updating till all the drawing is done. Try
for (i in 1:100){
mdat <- data.frame(100+i*5,100+i)
colnames(mdat) <- c("X","Y")
dev.hold() #pause device update
print(plot_field)
dev.flush() #send plot to device
}
Related Topics
Rename Columns by Pattern in R
Ggplot Bar Plot Side by Side Using Two Variables
Difference Between Sort(), Rank(), and Order()
How to Keep My Subtitles When I Use Ggplotly()
Addsma Not Drawn on Graph When Called from Function
R: Matrix by Vector Multiplication
Create a Reactive Function Outside the Shiny App
How to Specify the Size/Layout of a Single Plot to Match a Certain Grid in R
How to Apply Dplyr's Select(,Starts_With()) on Rows, Not Columns
R Lpsolve Binary Find All Possible Solutions
Remove Columns of Dataframe Based on Conditions in R
Loop Through a Series of Qplots
Let Ggplot2 Histogram Show Classwise Percentages on Y Axis
Plot with Ggplot in For-Loop Doesn't Work
How to Capture the Output of System()