0

I have have a dataset that contains some twins and triplets. For each set of twins or triplets I need to randomly select one to remain in the dataset. This information is coded in two columns, FamilyID, and FamilyOrder. Twins and triplets share both a FamilyID and FamilyOrder. Non-twin siblings share a FamilyID, but have different FamilyOrder values.


    FamilyID  FamilyOrder  y
    1         1            45
    1         2            33
    2         1            12
    3         1            76
    3         2            15
    3         2            59
    3         2            22
    4         1            56
    4         1            21

So, in this example code, FamilyID 3 contains one non-twin (coded as 1) and a set of triplets (coded as 2), and FamilyID 4 has a pair of twins.

I would like the output to be something like:

FamilyID  FamilyOrder  y
1         1            45
1         2            33
2         1            12
3         1            76
3         2            22
4         1            56

Which keeps regular siblings, but removes all but one for each twin and triplet.

wsen
  • 33
  • 4

3 Answers3

3

You can do this easily with dplyr...

library(dplyr)

df %>% 
  group_by(FamilyID, FamilyOrder) %>% 
  sample_n(1)

  FamilyID FamilyOrder     y
1        1           1    45
2        1           2    33
3        2           1    12
4        3           1    76
5        3           2    22
6        4           1    56
Andrew Gustar
  • 17,295
  • 1
  • 22
  • 32
0

You mentioned that you only need to pick a random one. So first() should be fine.

library(dplyr)
df %>%
    group_by(FamilyID,FamilyOrder) %>%
    mutate(y = first(y)) %>%
    ungroup()
yusuzech
  • 5,896
  • 1
  • 18
  • 33
0

Here are base and data.table equivalents.

library(data.table)

dt <- as.data.table(DF)
dt[, .(y = y[sample.int(length(y), 1)]), by = .(FamilyID, FamilyOrder)]

#equivalent base statements. only problem is that they're not sorted right. 
aggregate(DF$y
          , by =DF[, c('FamilyID', 'FamilyOrder')]
          , FUN = function(x) x[sample.int(length(x), 1)])

aggregate(y ~ FamilyID + FamilyOrder
          , data = DF
          , FUN = function(x) x[sample.int(length(x), 1)])

  FamilyID FamilyOrder  x
1        1           1 45
2        2           1 12
3        3           1 76
4        4           1 56
5        1           2 33
6        3           2 15

#super base for the first non-duplicate value
DF[!duplicated(DF[, names(DF) != 'y']), ]

  FamilyID FamilyOrder  y
1        1           1 45
2        1           2 33
3        2           1 12
4        3           1 76
5        3           2 15
8        4           1 56
Cole
  • 11,130
  • 1
  • 9
  • 24