Home > Net >  R: Loops Containing Lists and Data Frames
R: Loops Containing Lists and Data Frames

Time:04-08

I am working with the R programming language.

I wrote the following code for a loop that randomly sample integers (between 1-10) 5 times:

results <- list()

for (i in 1:5) {

n_1_i = sample(1:10, 1, replace=F)
n_2_i = sample(1:10, 1, replace=F)
n_3_i = sample(1:10, 1, replace=F)
n_4_i = sample(1:10, 1, replace=F)
n_5_i = sample(1:10, 1, replace=F)


iteration = i
 
results_tmp = data_frame(iteration, n_1_i, n_2_i, n_3_i, n_4_i, n_5_i)

  results[[i]] <- results_tmp

}

results_df <- data.frame(do.call(rbind.data.frame, results))

head(results_df)

  iteration n_1_i n_2_i n_3_i n_4_i n_5_i
1         1     5     9     7     5     5
2         2     5     4    10     1    10
3         3    10     4     6     2     3
4         4     5     6     1     6     1
5         5    10     6     3     7     4

Now, I would like to add 5 new columns to this data frame that contain "n" number of random integers. For example, in the first row:

  • n_1_i = 5 : I would like to make a column called "cond_1" such that cond_1 <- sample(1:10, 5, replace=F)

  • n_2_i = 9 : I would like to make a column called "cond_1" such that cond_2 <- sample(1:10, 9, replace=F)

  • n_3_i = 9 : I would like to make a column called "cond_1" such that cond_3 <- sample(1:10, 7, replace=F)

  • n_4_i = 9 : I would like to make a column called "cond_1" such that cond_4 <- sample(1:10, 5, replace=F)

  • n_5_i = 9 : I would like to make a column called "cond_1" such that cond_5 <- sample(1:10, 5, replace=F)

This would be repeated for each of the 5 rows.

I tried to incorporate this logic into the existing loop:

results <- list()

for (i in 1:5) {

n_1_i = sample(1:10, 1, replace=F)
n_2_i = sample(1:10, 1, replace=F)
n_3_i = sample(1:10, 1, replace=F)
n_4_i = sample(1:10, 1, replace=F)
n_5_i = sample(1:10, 1, replace=F)

var_1_cond_i = sample(1:10, n_1_i, replace=F)
var_2_cond_i = sample(1:10, n_2_i, replace=F)
var_3_cond_i = sample(1:10, n_3_i, replace=F)
var_4_cond_i = sample(1:10, n_4_i, replace=F)
var_5_cond_i = sample(1:10, n_5_i, replace=F)

iteration = i
 
results_tmp = data_frame(iteration, n_1_i, n_2_i, n_3_i, n_4_i, n_5_i)

list_tmp = list(var_1_cond_i, var_2_cond_i, var_3_cond_i, var_4_cond_i, var_5_cond_i)


results[[i]] <- results_tmp

results_list[[i]] <- list_tmp

}

results_df <- data.frame(do.call(rbind.data.frame, results, results_list))

But this is giving the following error: (I suspect that this error is because I am trying to mix lists with data frames?)

Error in if (quote) args <- lapply(args, enquote) : 
  argument is not interpretable as logical
In addition: Warning message:
In if (quote) args <- lapply(args, enquote) :
  the condition has length > 1 and only the first element will be used

In the end, I would like to produce something like this (I have shown an example of the first row):

  iteration n_1_i n_2_i n_3_i n_4_i n_5_i var_1_cond_i              var_2_cond_i         var_3_cond_i var_4_cond_i var_5_cond_i
1         1     5     9     7     5     5    9 4 6 7 3 2  8  3  6  7  5 10  4  1 10  2  3  1  7  6  5    8 1 3 9 4    8 1 3 4 6

Can someone please show me how to do this?

Thanks!

CodePudding user response:

Here's how I would rewrite the code. We start in long format to skip all copy/pasting of similarly named columns. This also generalizes easily if you want to change the number of draws per iteration. Then (if needed) pivot wider at the end. (Though I'd recommend keeping it in long format for working with it...)

library(dplyr)
library(purrr)
library(tidyr)

n_iter = 5
n_i = 5
set.seed(47)  ## for reproducibility - remove if you want new random numbers
results = expand.grid(iter = seq_len(n_iter), i = seq_len(n_i)) %>% 
  mutate(n = sample(1:10, size = n_iter * n_i, replace = TRUE))
results   
#    iter i  n
# 1     1 1  9
# 2     2 1  2
# 3     3 1  4
# 4     4 1  1
# 5     5 1 10
# 6     1 2  7
# 7     2 2  6
# ...

results = results %>%
  mutate(cond = map(n, ~sample(1:10, size = .x, replace = FALSE)))

results
#    iter i  n                          cond
# 1     1 1  9    5, 10, 8, 1, 9, 2, 7, 3, 4
# 2     2 1  2                          7, 8
# 3     3 1  4                    5, 8, 3, 1
# 4     4 1  1                             8
# 5     5 1 10 10, 2, 9, 3, 5, 8, 4, 6, 7, 1
# 6     1 2  7          7, 2, 10, 8, 6, 4, 3
# 7     2 2  6             5, 1, 7, 8, 6, 10
# ...

results = results %>%
  pivot_wider(
    id_cols = iter,
    values_from = c("n", "cond"),
    names_from = "i",
    names_glue = "{.value}_{i}"
)
results
# # A tibble: 5 × 11
#    iter   n_1   n_2   n_3   n_4   n_5 cond_1     cond_2    cond_3    cond_4     cond_5   
#   <int> <int> <int> <int> <int> <int> <list>     <list>    <list>    <list>     <list>   
# 1     1     9     7     8     5     3 <int [9]>  <int [7]> <int [8]> <int [5]>  <int [3]>
# 2     2     2     6     8    10     6 <int [2]>  <int [6]> <int [8]> <int [10]> <int [6]>
# 3     3     4     9     5     5     1 <int [4]>  <int [9]> <int [5]> <int [5]>  <int [1]>
# 4     4     1     6     4     2     5 <int [1]>  <int [6]> <int [4]> <int [2]>  <int [5]>
# 5     5    10     6     9     5     1 <int [10]> <int [6]> <int [9]> <int [5]>  <int [1]>

print.data.frame(results)
#   iter n_1 n_2 n_3 n_4 n_5                        cond_1                     cond_2                    cond_3                        cond_4
# 1    1   9   7   8   5   3    5, 10, 8, 1, 9, 2, 7, 3, 4       7, 2, 10, 8, 6, 4, 3   9, 6, 8, 4, 5, 10, 3, 1                 9, 5, 6, 7, 3
# 2    2   2   6   8  10   6                          7, 8          5, 1, 7, 8, 6, 10    8, 2, 7, 5, 4, 1, 9, 3 9, 5, 3, 6, 2, 1, 7, 10, 8, 4
# 3    3   4   9   5   5   1                    5, 8, 3, 1 5, 1, 4, 3, 6, 10, 7, 8, 9            9, 3, 10, 1, 4                8, 10, 1, 7, 6
# 4    4   1   6   4   2   5                             8           7, 3, 2, 1, 6, 4                3, 1, 2, 5                          1, 7
# 5    5  10   6   9   5   1 10, 2, 9, 3, 5, 8, 4, 6, 7, 1           1, 9, 3, 7, 8, 4 8, 4, 6, 7, 5, 1, 3, 9, 2                7, 6, 5, 8, 10
#              cond_5
# 1           2, 5, 9
# 2 2, 1, 10, 3, 6, 7
# 3                 8
# 4    10, 6, 2, 8, 1
# 5                 6
  • Related