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

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

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

Семьи будут состоять не более чем из 2 членов (поэтому они могут быть либо отдельными людьми, либо парами).

Для отдельных лиц (семей только с одной строкой, т. е. id = 5:10) я хочу создать столбец под названием «случайный», который случайным образом присваивает 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)

person Tom    schedule 01.06.2020    source источник


Ответы (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 и 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
person Ronak Shah    schedule 01.06.2020
comment
Это почти так, но мне нужно ровно 50% 1 и 0 (по 3 каждого) для 6 строк с уникальными значениями семейства (т.е. id == 5:10). Это дает мне случайное число 1 каждый раз. - person Tom; 01.06.2020
comment
Хорошо. Обновил ответ. Вы можете проверить сейчас? - person Ronak Shah; 01.06.2020

Использование data.table

library(data.table)
setDT(df)[, if(.N > 1) 0 else sample(0:1, 1), family]
person akrun    schedule 01.06.2020