Создайте случайную двоичную переменную для подмножества наблюдений, присвоив 1 определенной доле строк

У меня есть датафрейм...

df <- tibble(
  id = 1:10, 
  family = c("a","a","b","b","c", "d", "e", "f", "g", "h")
  )

Семьи могут состоять максимум из двух человек (по отдельности или парами).

Для отдельных лиц (семей только с одной строкой, т.е. id = 5:10) я хочу создать столбец с именем 'random', который случайным образом присваивает 50% записей как 1, а остальные как 0. Все остальные строки (принадлежащие к семьи с 2 членами) также должны равняться 0.

В итоге данные должны выглядеть следующим образом (в зависимости от того, каким 50% строк присвоено 1)...

df <- tibble(
  id = 1:10, 
  family = c("a","a","b","b","c", "d", "e", "f", "g", "h"),
  random = c(0, 0, 0, 0, 1, 0, 1, 1, 0, 0)
  )

Я в основном использую Tidyverse и хотел бы включить его в канал.

В настоящее время я пробую что-то вроде...

df %>%
   group_by(family) %>% 
   mutate(random = if(n() == 1) *not sure what goes here* else 0)

2 ответа

Мы можем присвоить 0, если количество строк в family больше 1, иначе выберите случайное значение от 0 до 1.

library(dplyr)

df %>%
  group_by(family) %>%
  mutate(random = if(n() > 1) 0 else sample(0:1, 1))

#      id family random
#   <int> <chr>   <dbl>
# 1     1 a           0
# 2     2 a           0
# 3     3 b           0
# 4     4 b           0
# 5     5 c           1
# 6     6 d           1
# 7     7 e           0
# 8     8 f           0
# 9     9 g           0
#10    10 h           0

Если нам нужно фиксированное количество единиц и нулей для групп с 1 значением, мы можем использовать

df %>%
  add_count(family) %>%
   mutate(n = replace(n, n > 1, 0),
          n = replace(n, {inds = which(n == 1);sample(inds, length(inds)/2)}, 0))


# A tibble: 10 x 3
#      id family     n
#   <int> <chr>  <dbl>
# 1     1 a          0
# 2     2 a          0
# 3     3 b          0
# 4     4 b          0
# 5     5 c          1
# 6     6 d          0
# 7     7 e          0
# 8     8 f          1
# 9     9 g          1
#10    10 h          0

С помощью data.table

library(data.table)
setDT(df)[, if(.N > 1) 0 else sample(0:1, 1), family]
Другие вопросы по тегам