cs0815
cs0815

Reputation: 17418

looping over resulting lists to amend column in data frame

The below is my clumsy (?) procedural attempt to append the results of a function fastNonDominatedSorting from the package nsga2R to a data frame. Maybe there is a simpler way to append the resulting lists to the dataframe?

library(nsga2R)

df <- data.frame(
    x = c(0,0.5,0.5,1.0)
    , y = c(0,1.0,1.0,1.0)
)
matrix <- data.matrix(df)

mo_sorting_results <- fastNonDominatedSorting(matrix)

rank <- 1
df$rank <- 0
for(a_list in mo_sorting_results) {

   for(list_element in a_list) {
       print(list_element)
       df[list_element,]$rank <- rank 
   }
   rank <- rank + 1
}

df

Upvotes: 2

Views: 32

Answers (1)

jay.sf
jay.sf

Reputation: 73502

When I understand your approach right, from the mo_sorting_results,

library("nsga2R")
mo_sorting_results <- fastNonDominatedSorting(matrix)
mo_sorting_results
# [[1]]
# [1] 1
# 
# [[2]]
# [1] 2 3
# 
# [[3]]
# [1] 4

you want the rank to be incremented by one by each list level like so?

df$rank <- unlist(mapply(rep, seq(mo_sorting_results), lengths(mo_sorting_results)))
df
#     x y rank
# 1 0.0 0    1
# 2 0.5 1    2
# 3 0.5 1    2
# 4 1.0 1    3

Benchmark

This would be around 15 times faster.

forloop <- function() {
  rank <- 1
  df$rank <- 0
  for (a_list in mo_sorting_results) {
    for (list_element in a_list) {
      df[list_element,]$rank <- rank 
      }
    rank <- rank + 1
  }
}

mapply1 <- function() {
  unlist(mapply(rep, seq(mo_sorting_results), lengths(mo_sorting_results)))
}

microbenchmark::microbenchmark(forloop(), mapply1())
# Unit: microseconds
#      expr     min       lq     mean  median      uq     max neval cld
# forloop() 523.290 533.7510 550.6793 539.619 548.804 750.619   100   b
# mapply1()  31.893  33.9335  37.1739  35.975  37.251  90.065   100  a 

Upvotes: 1

Related Questions