Thanks for the explanation! That does help to clarify things.
So there isn't any reasonable way that you would construct the plot you describe using both a for
loop and ggplot2
ā so I'd suggest thinking about how a for
loop might be part of preparing the data for plotting, rather than part of the plotting itself.
Something that's challenging about for
loops is that they are a very general purpose code tool that can be used in a number of different ways, so it can be hard to reason from simple examples if the example doesn't show the kind of usage you need.
One thing that might make the simple example you gave difficult to extend to your needs is that the code inside the loop doesn't actually make use of the loop variable (i
). Your example loop is accomplishing the same thing as just copying and pasting the code inside the loop five times.
z <- 1
for (i in 1:3){
z <- 2 * z
print(z)
}
#> [1] 2
#> [1] 4
#> [1] 8
# This has the same effect as if you'd written...
z <- 1
z <- 2 * z
print(z)
#> [1] 2
z <- 2 * z
print(z)
#> [1] 4
z <- 2 * z
print(z)
#> [1] 8
Created on 2018-10-18 by the reprex package (v0.2.1)
Things get a lot more interesting when the code in the loop depends on the loop variable somehow ā that allows you to take an existing list of things and "loop over it", applying the same complex operation to each item. In this usage, you typically treat the incrementing loop variable as an index number that grabs corresponding items. Now it's like you copied and pasted the code inside the loop, but each time you changed something to correspond with the list of things you are looping over.
some_zs <- c("Zoe", "Zelda", "Zebulon")
random_zs <- data.frame(
z_name = some_zs,
n = NA_integer_,
mean = NA_real_,
sd = NA_real_
)
random_zs
#> z_name n mean sd
#> 1 Zoe NA NA NA
#> 2 Zelda NA NA NA
#> 3 Zebulon NA NA NA
for (i in seq_along(some_zs)){
# For each name, find the number of characters in the name.
# Then draw that many random numbers from a normal distribution,
# find the mean and SD of the random numbers,
# and update the `random_zs` data frame with those values
random_zs$n[[i]] <- nchar(some_zs[i])
samples <- rnorm(random_zs$n[[i]])
random_zs$mean[[i]] <- mean(samples)
random_zs$sd[[i]] <- sd(samples)
}
# Here's the outcome for the data frame we were updating
random_zs
#> z_name n mean sd
#> 1 Zoe 3 -0.22104488 0.4738899
#> 2 Zelda 5 0.09132254 1.0937531
#> 3 Zebulon 7 -0.12718158 0.7068360
# `seq_along()?` Huh??
# This is an R function that's really useful in loops
# It takes a variable and generates a sequence "along" that variable.
# For various reasons, it's safer than writing `1:length(my_variable)`
seq_along(some_zs)
#> [1] 1 2 3
Created on 2018-10-18 by the reprex package (v0.2.1)
This loop accomplishes the same thing as this mess of copypasta:
random_zs$n[[1]] <- nchar(some_zs[1])
samples <- rnorm(random_zs$n[[1]])
random_zs$mean[[1]] <- mean(samples)
random_zs$sd[[1]] <- sd(samples)
random_zs$n[[2]] <- nchar(some_zs[2])
samples <- rnorm(random_zs$n[[2]])
random_zs$mean[[2]] <- mean(samples)
random_zs$sd[[2]] <- sd(samples)
random_zs$n[[3]] <- nchar(some_zs[3])
samples <- rnorm(random_zs$n[[3]])
random_zs$mean[[3]] <- mean(samples)
random_zs$sd[[3]] <- sd(samples)
For your task, you seem to be on your way to writing code that does what you need once (this is good!). You need to think about what variable you will "loop over", and how that variable fits into your code. If it helps, maybe try writing the horrible copypasta version first! Taking things step by step when you're learning a new kind of abstraction can be really helpful.