#r #dplyr #tidyverse
Вопрос:
Я пытаюсь отобрать одинаковое количество классов из двух фреймов данных разных размеров. Я могу сделать это вручную, но количество классов в некоторых моих фреймах данных довольно велико.
Я смог использовать эту dplyr::count
функцию, чтобы получить список интересующих классов из меньшего фрейма данных, а также их количество. Затем я извлекаю эти классы и их количество в виде векторов. Затем я попытался создать функцию с использованием этих векторов и вызвать ее с помощью mapply
, чтобы я мог создавать отфильтрованные фрагменты для каждого класса , а затем повторно присоединяться к спискам с помощью do.call
, но при попытке запуска я получаю ошибки mapply
.
Ниже приведены примеры наборов данных. df-это меньший фрейм данных , содержащий ControlVarA == "Group_1"
6 строк и 10 строк ControlVarA == "Group_2"
, и я хочу извлечь такое же количество строк/классов из большего фрейма данных df2 (который содержит 6 строк ControlVarA == "Group_1"
и 20 строк ControlVarA == "Group_2"
).
df <- data.frame("ID" = 1:16)
df$VarA <- c(1,1,1,1,1,1,1,1,1,1,1,14,NA_real_,NA_real_,NA_real_,16)
df$VarB <- c(10,0,0,0,12,12,12,12,0,14,NA_real_,14,16,16,16,16)
df$VarC <- c(10,12,14,16,10,12,14,16,10,12,14,16,10,12,14,16)
df$VarD <- c(10,12,14,16,10,12,14,16,10,12,14,16,10,12,14,16)
df$ControlVarA <- factor(c("Group_1","Group_1","Group_1","Group_1","Group_1", "Group_1",
"Group_2","Group_2","Group_2","Group_2","Group_2","Group_2",
"Group_2","Group_2","Group_2","Group_2"))
df
df2 <- data.frame("ID" = 1:26)
df2$VarA <- c(1,1,1,1,1,1,1,1,1,1,1,14,NA_real_,NA_real_,NA_real_,16,16,16,16,16,16,16,16,16,16,16)
df2$VarB <- c(10,0,0,0,12,12,12,12,0,14,NA_real_,14,16,16,16,16,16,16,16,16,16,16,16,16,16,16)
df2$VarC <- c(10,12,14,16,10,12,14,16,10,12,14,16,10,12,14,16,16,16,16,16,16,16,16,16,16,16)
df2$VarD <- c(10,12,14,16,10,12,14,16,10,12,14,16,10,12,14,16,16,16,16,16,16,16,16,16,16,16)
df2$ControlVarA <- factor(c("Group_1","Group_1","Group_1","Group_1","Group_1", "Group_1",
"Group_2","Group_2","Group_2","Group_2","Group_2","Group_2",
"Group_2","Group_2","Group_2","Group_2","Group_2","Group_2",
"Group_2","Group_2","Group_2","Group_2","Group_2","Group_2","Group_2","Group_2"))
df2
Чтобы извлечь имена классов и количество классов, я использую приведенный ниже код.
slice_vars <- df %>%
count(ControlVarA) %>%
filter(!is.na(.)) %>%
t() %>%
janitor::row_to_names(1) %>%
colnames()
slice_nums <- df %>%
count(ControlVarA) %>%
filter(!is.na(.)) %>%
t() %>%
janitor::row_to_names(2) %>%
as.data.frame() %>%
rename_with(~ gsub(" ", "", .x)) %>%
colnames() %>%
as.numeric()
function
Я создал и mapply
инструкция ниже
func_group <- function(dataset, x, y) {
dataset %>%
group_by(ControlVarA) %>%
slice_sample(n = all_of(x)) %>%
ungroup() %>%
filter(ControlVarA == data[[y]])
}
combine_lists <- mapply(func_group, slice_nums, slice_vars, MoreArgs = list(dataset = df2))
do.call(rbind, combine_lists)
Ответ №1:
count
чтобы получить количество строк для каждого значения ControlVarA
, объединитесь df2
и выберите n
случайные строки из каждой группы с помощью sample_n
. (К сожалению, slice_sample(n = first(n))
возвращает ошибку)
library(dplyr)
df %>%
count(ControlVarA) %>%
left_join(df2, by = 'ControlVarA') %>%
group_by(ControlVarA) %>%
sample_n(first(n)) %>%
ungroup %>%
select(-n)
# ControlVarA ID VarA VarB VarC VarD
# <fct> <int> <dbl> <dbl> <dbl> <dbl>
# 1 Group_1 1 1 10 10 10
# 2 Group_1 4 1 0 16 16
# 3 Group_1 3 1 0 14 14
# 4 Group_1 2 1 0 12 12
# 5 Group_1 5 1 12 10 10
# 6 Group_1 6 1 12 12 12
# 7 Group_2 12 14 14 16 16
# 8 Group_2 25 16 16 16 16
# 9 Group_2 15 NA 16 14 14
#10 Group_2 22 16 16 16 16
#11 Group_2 9 1 0 10 10
#12 Group_2 8 1 12 16 16
#13 Group_2 24 16 16 16 16
#14 Group_2 21 16 16 16 16
#15 Group_2 7 1 12 14 14
#16 Group_2 14 NA 16 12 12
Ответ №2:
library(tidyverse)
df <- data.frame("ID" = 1:16)
df$VarA <- c(1,1,1,1,1,1,1,1,1,1,1,14,NA_real_,NA_real_,NA_real_,16)
df$VarB <- c(10,0,0,0,12,12,12,12,0,14,NA_real_,14,16,16,16,16)
df$VarC <- c(10,12,14,16,10,12,14,16,10,12,14,16,10,12,14,16)
df$VarD <- c(10,12,14,16,10,12,14,16,10,12,14,16,10,12,14,16)
df$ControlVarA <- factor(c("Group_1","Group_1","Group_1","Group_1","Group_1", "Group_1",
"Group_2","Group_2","Group_2","Group_2","Group_2","Group_2",
"Group_2","Group_2","Group_2","Group_2"))
df2 <- data.frame("ID" = 1:26)
df2$VarA <- c(1,1,1,1,1,1,1,1,1,1,1,14,NA_real_,NA_real_,NA_real_,16,16,16,16,16,16,16,16,16,16,16)
df2$VarB <- c(10,0,0,0,12,12,12,12,0,14,NA_real_,14,16,16,16,16,16,16,16,16,16,16,16,16,16,16)
df2$VarC <- c(10,12,14,16,10,12,14,16,10,12,14,16,10,12,14,16,16,16,16,16,16,16,16,16,16,16)
df2$VarD <- c(10,12,14,16,10,12,14,16,10,12,14,16,10,12,14,16,16,16,16,16,16,16,16,16,16,16)
df2$ControlVarA <- factor(c("Group_1","Group_1","Group_1","Group_1","Group_1", "Group_1",
"Group_2","Group_2","Group_2","Group_2","Group_2","Group_2",
"Group_2","Group_2","Group_2","Group_2","Group_2","Group_2",
"Group_2","Group_2","Group_2","Group_2","Group_2","Group_2","Group_2","Group_2"))
df <- as_tibble(df) %>%
mutate(table = "df")
df2 <- as_tibble(df2) %>%
mutate(table = "df2")
final_df <- df %>%
bind_rows(df2)
set.seed(2021)
final_df %>%
filter(!if_any(.cols = VarA:VarD, is.na)) %>%
group_by(table, ControlVarA) %>%
slice_sample(n = 5)
#> # A tibble: 20 x 7
#> # Groups: table, ControlVarA [4]
#> ID VarA VarB VarC VarD ControlVarA table
#> <int> <dbl> <dbl> <dbl> <dbl> <fct> <chr>
#> 1 6 1 12 12 12 Group_1 df
#> 2 2 1 0 12 12 Group_1 df
#> 3 3 1 0 14 14 Group_1 df
#> 4 5 1 12 10 10 Group_1 df
#> 5 4 1 0 16 16 Group_1 df
#> 6 16 16 16 16 16 Group_2 df
#> 7 9 1 0 10 10 Group_2 df
#> 8 8 1 12 16 16 Group_2 df
#> 9 10 1 14 12 12 Group_2 df
#> 10 7 1 12 14 14 Group_2 df
#> 11 1 1 10 10 10 Group_1 df2
#> 12 4 1 0 16 16 Group_1 df2
#> 13 3 1 0 14 14 Group_1 df2
#> 14 2 1 0 12 12 Group_1 df2
#> 15 6 1 12 12 12 Group_1 df2
#> 16 22 16 16 16 16 Group_2 df2
#> 17 23 16 16 16 16 Group_2 df2
#> 18 9 1 0 10 10 Group_2 df2
#> 19 18 16 16 16 16 Group_2 df2
#> 20 20 16 16 16 16 Group_2 df2
Создано 2021-07-13 пакетом reprex (v2.0.0)
Комментарии:
1. Спасибо Десмонд, но я пытался найти решение, которое дало бы мне такое же количество отсчетов в исходном фрейме данных df, как и в более крупном df2. Т. Е. Мне нужно отфильтровать 6 строк с Group_1 и 10 строк с Group_2 из df 2. Исходный df2 содержит 6 строк с Group_1 и 20 строк с Group_2