Я пытаюсь повторно добавлять столбцы в фрейм данных, используя случайную выборку из другого фрейма данных.
Мой первый фрейм данных с фактическими данными для выборки выглядит так
df <- data.frame(cat = c("a", "b", "c","a", "b", "c"),
x = c(6,23,675,1,78,543))
У меня есть еще один фрейм данных:
df2 <- data.frame(obs =c(1,2,3,4,5,6,7,8,9,10),
cat=c("a", "a", "a", "b", "b", "b", "c","c","c", "c"))
Я хочу добавить 1000 новых столбцов в df2, которые случайным образом выбираются из df, сгруппированные по кат. Однажды я придумал (вероятно, очень любительский) способ сделать это, используя slice_sample() для создания нового образца данных dataframe1 со случайным образцом df, а затем объединив sample1 с df2.
df <- df %>%
group_by(cat)
df2 <- df2 %>%
group_by(cat)
sample1 <- slice_sample(df, preserve = T, n=3, replace = T )
sample1 <- sample1 %>%
ungroup() %>%
mutate(obs=c(1:9)) %>%
select(-cat)
df3 <- merge(df2,sample1, by= "obs")
Теперь я хочу найти способ повторить это 1000 раз, чтобы получить df3 с 1000 столбцами (x1,x2,x3 и т. д.)
Я просмотрел повторяющиеся циклы, но не смог понять, как заставить приведенный выше код работать внутри цикла.
Можно создать функцию, а затем использовать либо replicate
, либо rerun
(из purrr
) перед выполнением соединения.
library(dplyr)
library(purrr)
library(stringr)
f1 <- function(dat1) {
dat1 %>%
group_by(cat) %>%
slice_sample(n = 3, replace = TRUE) %>%
ungroup() %>%
mutate(obs = row_number()) %>%
select(-cat)
}
n <- 10
out <- rerun(10, f1(df)) %>%
c(list(df2), .) %>%
reduce(inner_join, by = 'obs') %>%
rename_at(vars(starts_with('x')), ~ str_c('x', seq_along(.)))
Вот вариант data.table
, который может помочь
dt <- as.data.table(df)
dt2 <- as.data.table(df2)
n <- 1000
res <- cbind(
dt2[, .(obs)],
dt2[
,
replicate(n, sample(dt[.BY, x, on = "cat"], .N, replace = TRUE), simplify = FALSE),
cat
]
)
Вы можете сохранить только 3 X уникальных строк значений cat
в df2
. Используйте replicate
, чтобы повторить процесс выборки n
раз и добавить n
новых столбцов.
library(dplyr)
n <- 10
df2 <- df2 %>% slice(1:(3*n_distinct(cat)))
df2[paste0('x', 1:n)] <- replicate(n, df %>%
group_by(cat) %>%
slice_sample(n = 3, replace = TRUE) %>%
pull(x))
# obs cat x1 x2 x3 x4 x5 x6 x7 x8 x9 x10
#1 1 a 6 1 1 6 6 1 1 1 6 6
#2 2 a 6 1 1 1 1 6 1 1 1 1
#3 3 a 1 6 1 6 1 6 6 1 6 6
#4 4 b 78 78 78 23 78 78 78 78 23 23
#5 5 b 78 78 78 23 23 23 78 78 78 23
#6 6 b 78 78 23 78 78 78 23 23 78 23
#7 7 c 675 543 543 543 543 543 675 543 543 675
#8 8 c 543 543 675 675 675 675 675 543 675 543
#9 9 c 543 543 675 543 675 543 675 675 543 675
Я думаю, вы можете обернуть это в функцию и использовать
replicate(1000, call_your_fn)