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