Plotting during a loop in RStudio
One thing you can do is open a x11 window and plot in there:
x11()
Plotz()
That should work the same as running it in terminal.
Multiple plots using loops in R
A simple approach with loops would be
for (cat in unique(x_1)){
d <- subset(A, x_1 == cat)
plot(d$z_1, d$z_2)
}
unique(x_1)
gets you all the unique values of x_1
. Then, for each of these values get a corresponding subset and use this subset for plotting.
R - plotting points on the same plot in for loop
You can use the points
function once a plot
has been called:
lambda <- runif(10,min=0,max=3)
mean(lambda)
## First plot
N <- rpois(1,mean(lambda))
plot(1,mean(N), xlim = c(1,10))
## Subsequent points
for (i in 2:10){
N <- rpois(i,mean(lambda))
points(i,mean(N))
}
Loop through multiple columns and make a plot for each in R?
Assuming your dataframe is df
,
library(ggplot2)
col_names <- colnames(df)
col_names <- col_names[-1]
for (i in col_names){
plot <- ggplot(df, aes_string(x=df$Year, y=i)) +
geom_point()
print(plot)
}
This should return them as individual plots.
edit: to return plots in the same view, and save as pdf,
col_names <- colnames(df)
col_names <- col_names[-1]
plot_list <- list()
for (i in col_names){
plot <- ggplot(df, aes_string(x=df$Year, y=i)) +
geom_point()
plot_list[[i]] <- plot
}
plot_grob <- arrangeGrob(grobs=plot_list)
pdf("testUSgraph.pdf")
grid.arrange(plot_grob)
dev.off()
(The problem with saving pdf in your initial code might be because you forgot the parentheses, dev.off
should be dev.off()
)
How to plot a series of points on the same graph in for loop
You points are "erased" because you are creating a new plot every time you call the plot
command. One way around this is to create and empty plot with plot
and then add points with the points
command inside the loop:
# empty plot
plot(x=NA, y=NA, xlim=c(1,10), ylim=c(1,10), xlab="", ylab="", main="")
# add points
for (i in 1:10) {
points(x=rep(i,i), y=1:i, pch=20)
}
Plots overwriting, so at the end of the R loop all have pulled from last element of list. What am I doing wrong?
Consider the following general tips in R and maybe even programming:
Variables: Avoid use of too many variables but interact directly on existing objects. This enhances the maintainability of environment variables. Some examples of redundancy include:
titlenames <- c(harps)
nam <- paste("data_percentage_", i, sep ="")
data_percentage_list <- lapply(paste0("data_percentage_",1:length(harps)), get)Names: Use more informative names for objects as
Y
does not inform code readers or yourself in the future. It appears to be a list that contains subsets of larger data framehotel_report
. More informative names likehotel_reports_df_list
quickly detail its contents and type (i.e., data frames within a list).Indentation: Always indent code in
for
loops (which can be automated in RStudio with keys: Ctrl/cmd + i) and even inside context managers likepdf
,with
, etc. This enhances readability and maintainability.Assign/Get: Avoid
assign
andget
which usually are not recommended in R. Instead, directly save your objects as items in lists. First loop can bypass the need to assign child items as separate variables:data_pct_matrix_list <- lapply(seq_along(harps), function(i) {
counts <- table(Y[[i]][[5]], Y[[i]][[3]])
pct_matrix <- apply(counts, 2, function(x) { x*100/sum(x, na.rm=TRUE)})
return(pct_matrix)
})Also last
assign
wrapped aroundbarplot
can also be refactored:plot_list <- lapply(data_percentage_matrix_list, function(mat) {
barplot(mat, main = "Breakdown of Property Score Distribution", sub = hotelname,
col = coul, las = 1, cex.names = .6, horiz = TRUE, yaxs="i", xlab = "Percentage",
cex.axis = .8, cex.lab = .8, cex.main = .8, cex.sub = .8))
})Loops: Avoid multiple
for
or nested loops as much as possible. In R,lapply
is a hidden loop. Your issues of 391 plots in each of the 391 PDFs likely is due to nestedlapply
within afor
loop. Consider these steps:- First, think about your process on one data frame object. Even generalize it in a separate function.
- Then, think about what exactly changes that can be iterated.
R's apply family includes more than just
apply
andlapply
such asmapply
that can run elementwise looping to flatten your nested iterations orby
(object-oriented wrapper totapply
) that can subset data frames by factor columns and run operations on them.
Without seeing sample data, consider following approaches which will need to be tested against data. Below assumes Y
is defined as list of subsets from hotel_report
data frame by Harp Number
.
mapply
/ Map
approach
Iterate elementwise between equal-length objects, data_pct_matrix_list
and harps
.
data_pct_matrix_list <- lapply(seq_along(harps), function(i) {
counts <- table(Y[[i]]$`Score Label`, Y[[i]]$`Question ID`)
pct_matrix <- apply(counts, 2, function(x) { x*100/sum(x, na.rm=TRUE) })
return(pct_matrix)
})
build_pdf <- function(data, harp) {
# For Hotel Name Subtitle
hotelname <- hotel_report$`Hotel (Q15 1)`[hotel_report$`Harp Number` == harp]
# Plot the Data
pdf(file = paste0(harp, ".pdf"), paper = "USr", width=8, height=7)
par(mar = c(5.1, 7, 4.1, 2.1))
hotel_plot <- barplot(data, main = "Breakdown of Property Score Distribution", sub = hotelname,
col = coul, las = 1, cex.names = .6, horiz = TRUE, yaxs="i", xlab = "Percentage",
cex.axis = .8, cex.lab = .8, cex.main = .8, cex.sub = .8))
dev.off()
return(hotel_plot)
}
plot_list <- Map(build_pdf, data_pct_matrix_list, harps)
# EQUIVALENTLY:
plot_list <- mapply(build_pdf, data_pct_matrix_list, harps, SIMPLIFY=FALSE)
by
approach
Subset hotel_report
data frame by unique Harp Number
and iteratively run on each subset to build pct_matrix
and hotel_plot
. This approach combines matrix build and plot steps.
build_pdf <- function(sub_df) {
# Matrix build
counts <- table(sub_df$`Score Label`, sub_df$`Question ID`)
pct_matrix <- apply(counts, 2, function(x) { x*100/sum(x, na.rm=TRUE) })
# For Hotel Name Subtitle
hotelname <- sub_df$`Hotel (Q15 1)`[1]
harp <- sub_df$`Harp Number`[1]
# Plot the Data
pdf(file = paste0(harp, ".pdf"), paper = "USr", width=8, height=7)
par(mar = c(5.1, 7, 4.1, 2.1))
hotel_plot <- barplot(pct_matrix, main = "Breakdown of Property Score Distribution", sub = hotelname,
col = coul, las = 1, cex.names = .6, horiz = TRUE, yaxs="i", xlab = "Percentage",
cex.axis = .8, cex.lab = .8, cex.main = .8, cex.sub = .8))
dev.off()
return(hotel_plot)
}
plot_list <- by(hotel_report, hotel_report$`Harp Number`, build_pdf)
# NEAR EQUIVALENT
plot_list <- lapply(split(hotel_report, hotel_report$`Harp Number`), build_pdf)
Update plots during for loop from within Rstudio?
Start up a separate graphics device with X11()
(or win()
on windows?) and use that.
Although plots seem to update okay on my RStudio setup. My test is simply:
plot(1:10);for(i in 1:10){points(10-i,i);Sys.sleep(1)}
I see the first set of 10 points, then the next set appear at one second intervals, in the RStudio embedded graphics window.
Related Topics
How to Rbind Vectors Matching Their Column Names
How to Create Md5 Hash of a Column in R
Convert Factor to Integer in a Data Frame
Replicate Each Row of Data.Frame and Specify the Number of Replications for Each Row
Formatting a Date in R Without Leading Zeros
How to Change Line Width in Ggplot
Normalizing Y-Axis in Histograms in R Ggplot to Proportion by Group
How to Best Simulate an Arbitrary Univariate Random Variate Using Its Probability Function
How to Check If a Column Is a Date in R
Warning Message: Line Appears to Contain Embedded Nulls
Dplyr Piping Data - Difference Between '.' and '.X'
R::Ggplot2::Geom_Points: How to Swap Points with Pie Charts
How to Filter Data Without Losing Na Rows Using Dplyr