Plotting During a Loop in Rstudio

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 frame hotel_report. More informative names like hotel_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 like pdf, with, etc. This enhances readability and maintainability.

  • Assign/Get: Avoid assign and get 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 around barplot 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 nested lapply within a for loop. Consider these steps:

    1. First, think about your process on one data frame object. Even generalize it in a separate function.
    2. Then, think about what exactly changes that can be iterated.

    R's apply family includes more than just apply and lapply such as mapply that can run elementwise looping to flatten your nested iterations or by (object-oriented wrapper to tapply) 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



Leave a reply



Submit