A solution uses tidyverse. The key is to split the data frame by row and apply a function to sample the values for each row subset. map_df can achieve the above-mentioned task and combine all the output to a data frame. df2 is the final output.
# Load package library(tidyverse) # Set seed set.seed(123) # Create example data frame df <- data.frame(matrix(nrow = 57, ncol = 6)) %>% mutate( X1 = round(rnorm(n = 57, mean = 0, sd = 1), 1), X2 = round(rnorm(n = 57, mean = 0, sd = 1), 1), X3 = round(rnorm(n = 57, mean = 0, sd = 1), 1), X4 = round(rnorm(n = 57, mean = 0, sd = 1), 1), X5 = round(rnorm(n = 57, mean = 0, sd = 1), 1), X6 = round(rnorm(n = 57, mean = 0, sd = 1), 1) ) # Process the data df2 <- df %>% rowid_to_column() %>% split(f = .$rowid) %>% map_df(function(dt){ dt_sub <- dt %>% select(-rowid) %>% select(sample(1:6, 3, replace = FALSE)) %>% unite(X7, everything(), sep = ", ") return(dt_sub) }) %>% bind_cols(df) %>% select(paste0("X", 1:7)) df2 X1 X2 X3 X4 X5 X6 X7 1 -0.6 0.6 0.5 0.1 0.9 0.1 0.1, 0.5, 0.9 2 -0.2 0.1 0.3 0.0 -1.0 0.2 0.1, 0.3, 0.2 3 1.6 0.2 0.1 2.1 2.0 1.6 1.6, 2.1, 0.1 4 0.1 0.4 -0.6 -0.7 -0.1 -0.2 0.1, 0.4, -0.6 5 0.1 -0.5 -0.8 -1.1 0.2 0.2 0.1, 0.2, -0.5 6 1.7 -0.3 -1.0 0.0 -0.7 1.2 -1, -0.7, -0.3 7 0.5 -1.0 0.1 0.3 -0.6 1.1 0.5, -0.6, -1 ...
rowwiseand usesample(1:6, 1, replace = F). Sample just one column not 3. BTW, whystr_c? Don't you want to fillX7with numbers? Like this you will have characters.