Измените формат данных так, чтобы у соответствующих членов семьи был свой собственный столбец - PullRequest
1 голос
/ 04 марта 2020

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

df <- tibble(
  id = 1:5, 
  family = c("a","a","b","b","c"), 
  twin = c(1,2,1,2,1), 
  datacol1 = 11:15, 
  datacol2 = 21:25
  )

Для каждой пары близнецов (членов одного семейства) мне нужно иметь второй «datacol» с данными других близнецов. Это должно происходить только для совпадающих близнецов, поэтому в 5-й строке (из семейства "c") должны быть повторяющиеся пустые столбцы.

В идеале к концу данные должны выглядеть следующим образом ...

df <- tibble(
  id = 1:5, 
  family = c("a","a","b","b","c"), 
  twin = c(1,2,1,2,1), 
  datacol1 = 11:15,
  datacol1.b = c(12,11,14,13,NA),
  datacol2 = 21:25, 
  datacol2.b = c(22,21,24,23,NA)
  )

Я добавил изображение, чтобы проиллюстрировать, к чему я пытаюсь добраться.

enter image description here

Я хотел бы быть в состоянии сделать это для всех столбцов или для выбранных столбцов и, предпочтительно, с помощью Tidyverse.

Ответы [ 2 ]

2 голосов
/ 04 марта 2020

Мы также можем использовать mutate_at

library(dplyr)
df %>% 
    group_by(family) %>%
    mutate_at(vars(starts_with('datacol')), list(`2` = 
           ~if(n() == 1) NA_integer_ else rev(.)))
# A tibble: 5 x 7
# Groups:   family [3]
#     id family  twin datacol1 datacol2 datacol1_2 datacol2_2
#  <int> <chr>  <dbl>    <int>    <int>      <int>      <int>
#1     1 a          1       11       21         12         22
#2     2 a          2       12       22         11         21
#3     3 b          1       13       23         14         24
#4     4 b          2       14       24         13         23
#5     5 c          1       15       25         NA         NA
1 голос
/ 04 марта 2020
cols = c("datacol1", "datacol2")
df %>%
    group_by(family) %>%
    mutate_at(vars(cols), function(x){
        if (n() == 2){
            rev(x)
        } else {
            NA
        }
    }) %>%
    ungroup() %>%
    select(cols) %>%
    rename_all(funs(paste0(., ".b"))) %>%
    cbind(df, .)

База R

cols = c("datacol1", "datacol2")
do.call(rbind, lapply(split(df, df$family), function(x){
    cbind(x, setNames(lapply(x[cols], function(y) {
        if (length(y) == 2) {
            rev(y)
        } else {
            NA
        }}),
        paste0(cols, ".b")))
}))
...