How to convert this part of my function into a loop to reduce the redundancy?

Hi,

Welcome to the RStudio community!

There are several ways of going about what you like to to do. I present here a way I think is one of the most elegant with fewest lines of code. Although you provided us with your code, you did not create a reprex so I was not able to use any of your data or generate results specific for your question. Next time, please read the guide on how to create one so people will be able to answer faster. A reprex consists of the minimal code and data needed to recreate the issue/question you're having. You can find instructions how to build and share one here:

Here is an example of the technique with dummy data

library(ggplot2)

#The data for the base plot
baseData = data.frame(x = 1:10/10, y = runif(10))

#A list of parameters for all additional shapes that are different
shapeData = list(
  list(data = 10, colour = "red"),
  list(data = 30, colour = "green"),
  list(data = 50, colour = "blue"))

#Building the ggplot with all other shapes
ggplot(baseData, aes(x = x, y = y)) + geom_point() +
  sapply(shapeData, function(myData){
    geom_vline(xintercept = myData$data / 100, 
               colour = myData$colour, size = 2)
  })


Created on 2020-11-22 by the reprex package (v0.3.0)

Explanation
In ggplot, you can add multiple shapes at once by using the sapply() function from R. I created a list of lists (shapeData) where I storde all the parts that are different per shape. In your case that would be percent, col, alpha,..). When I use the apply function, I can then generate the same shape as many times as I have items in my list, and put the defined values in places I need them. If I have values that are the same for all shapes, I can just hard code them in (e.g. in my example size, in yours lwd or the first alpha). The result is a very clean ggplot code with a lot of redundancy saved.

If you need to add multiple ggplot object in every iteration, like for you tm_shape, tm_borders, tm_fill you either repeat this process, or make list of object to return like this:

ggplot(baseData, aes(x = x, y = y)) + geom_point() +
  sapply(shapeData, function(myData){
    list(geom_vline(xintercept = myData$data / 100, 
               colour = myData$colour, size = 2),
         geom_point(aes(x = myData$data / 100 + 0.05, 
                        y = 0.5, size = 3)))
  }) 

OR

ggplot(baseData, aes(x = x, y = y)) + geom_point() +
  sapply(shapeData, function(myData){
    geom_vline(xintercept = myData$data / 100, 
                    colour = myData$colour, size = 2)
  }) +
 sapply(shapeData, function(myData){
    geom_point(aes(x = myData$data / 100 + 0.05, 
                   y = 0.5, size = 3))
  })

image

Hope this helps,
PJ