How can I avoid complex for loops?

You could also define a function first ..

f <- function(data) {

  # sort data by flow
  data <- data[order(data['flow'], decreasing = TRUE), ]

  # apply your functions
  data["area_portion"] <- data['Area'] / sum(data['Area']) * 100
  data["flow_portion"] <- data['flow'] / sum(data['flow']) * 100
  data["cum_area"] <- cumsum(data['area_portion'])
  data["cum_flow"] <- cumsum(data['flow_portion'])
  data
  }

.. and use lapply to, ahhm, apply f to your list

out <- lapply(files, f)
out
#[[1]]
#  Area flow area_portion flow_portion  cum_area  cum_flow
#1    4    1     26.66667     33.33333  26.66667  33.33333
#2    6    1     40.00000     33.33333  66.66667  66.66667
#3    5    1     33.33333     33.33333 100.00000 100.00000

#[[2]]
#  Area flow area_portion flow_portion  cum_area cum_flow
#2    8    2     44.44444           50  44.44444       50
#1    6    1     33.33333           25  77.77778       75
#3    4    1     22.22222           25 100.00000      100

If you want to change the names of out you can use setNames

out <- setNames(lapply(files, f), paste0(c("A", "B"), "_sorted"))
# or
# out <- setNames(lapply(files, f), paste0(unlist(frames), "_sorted"))

Using lapply to loop over files and dplyr mutate to add new columns

library(dplyr)

setNames(lapply(files, function(x) 
          x %>%
            arrange(desc(flow)) %>%
            mutate(area_portion = Area/sum(Area)*100, 
                   flow_portion = flow/sum(flow) * 100, 
                   cum_area = cumsum(area_portion),
                   cum_flow = cumsum(flow_portion))
),paste0(frames, "_sorted"))


#$A_sorted
#  Area flow area_portion flow_portion  cum_area  cum_flow
#1    4    1     26.66667     33.33333  26.66667  33.33333
#2    6    1     40.00000     33.33333  66.66667  66.66667
#3    5    1     33.33333     33.33333 100.00000 100.00000

#$B_sorted
#  Area flow area_portion flow_portion  cum_area cum_flow
#1    8    2     44.44444           50  44.44444       50
#2    6    1     33.33333           25  77.77778       75
#3    4    1     22.22222           25 100.00000      100

Or completely going tidyverse way we can change lapply with map and setNames with set_names

library(tidyverse)

map(set_names(files, str_c(frames, "_sorted")), 
  . %>% arrange(desc(flow)) %>%
  mutate(area_portion = Area/sum(Area)*100, 
         flow_portion = flow/sum(flow) * 100, 
         cum_area = cumsum(area_portion),
         cum_flow = cumsum(flow_portion)))

Updated the tidyverse approach following some pointers from @Moody_Mudskipper.

Tags:

For Loop

R