dplyr::coalesce, ma per più righe

Aug 21 2020

Ho del codice che emette un elenco di frame di dati, che contengono alcuni metadati e diversi set di misurazioni. Devo essere in grado di elaborare l'elenco dei frame di dati e restituire un singolo frame di dati, "schiacciando" i valori NA in singole righe, dove i metadati sono gli stessi. Mi piacerebbe usare le funzioni dplyr se possibile.

Ho provato più tipi di join, bind_rows, bind_cols (quindi rimuovi i duplicati), la funzione coalesce (che sembrava promettente, ma funziona solo per una riga, non per più.

L'inserimento dei dati è estremamente variabile, con diversi numeri di misurazioni.

Un esempio di ciò con cui sto iniziando:

dfs <- list(
  df1 = tibble(
    exp = "EXP1",
    stage = "Stage1",
    section = rep(101:105, each = 2),
    meas1 = c(29L, 30L, 20L, 23L, 25L, 28L, 21L, 26L, 24L, 22L)
  ),
  df2 = tibble(
    exp = "EXP1",
    stage = "Stage1",
    section = 101:105,
    meas2 = 30:34
  ),
  df3 = tibble(
    exp = "EXP1",
    stage = "Stage2",
    section = 101:105,
    meas2 = 40:44
  )
)

$df1
# A tibble: 10 x 4
   exp   stage  section meas1
   <chr> <chr>    <int> <int>
 1 EXP1  Stage1     101    29
 2 EXP1  Stage1     101    30
 3 EXP1  Stage1     102    20
 4 EXP1  Stage1     102    23
 5 EXP1  Stage1     103    25
 6 EXP1  Stage1     103    28
 7 EXP1  Stage1     104    21
 8 EXP1  Stage1     104    26
 9 EXP1  Stage1     105    24
10 EXP1  Stage1     105    22

$df2
# A tibble: 5 x 4
  exp   stage  section meas2
  <chr> <chr>    <int> <int>
1 EXP1  Stage1     101    30
2 EXP1  Stage1     102    31
3 EXP1  Stage1     103    32
4 EXP1  Stage1     104    33
5 EXP1  Stage1     105    34

$df3
# A tibble: 5 x 4
  exp   stage  section meas2
  <chr> <chr>    <int> <int>
1 EXP1  Stage2     101    40
2 EXP1  Stage2     102    41
3 EXP1  Stage2     103    42
4 EXP1  Stage2     104    43
5 EXP1  Stage2     105    44

Un esempio di ciò che spero di concludere:

    result <- tibble(
  exp = "EXP1",
  stage = c(rep('Stage1', 10), rep('Stage2', 5)),
  section = c(rep(101:105, each = 2), 101:105),
  meas1 = c(c(29L, 30L, 20L, 23L, 25L, 28L, 21L, 26L, 24L, 22L), rep(NA_real_, 5)),
  meas2 = c(30, NA_real_, 31, NA_real_, 32, NA_real_, 33, NA_real_, 34, NA_real_, 40:44)
)



 # A tibble: 15 x 5
   exp   stage  section meas1 meas2
   <chr> <chr>    <int> <dbl> <dbl>
 1 EXP1  Stage1     101    29    30
 2 EXP1  Stage1     101    30    NA
 3 EXP1  Stage1     102    20    31
 4 EXP1  Stage1     102    23    NA
 5 EXP1  Stage1     103    25    32
 6 EXP1  Stage1     103    28    NA
 7 EXP1  Stage1     104    21    33
 8 EXP1  Stage1     104    26    NA
 9 EXP1  Stage1     105    24    34
10 EXP1  Stage1     105    22    NA
11 EXP1  Stage2     101    NA    40
12 EXP1  Stage2     102    NA    41
13 EXP1  Stage2     103    NA    42
14 EXP1  Stage2     104    NA    43
15 EXP1  Stage2     105    NA    44

Grazie per qualsiasi aiuto possiate darmi. Dopo diversi anni di programmazione R, questa è la mia prima domanda posta su SO. Sono sempre stato in grado di capirlo usando SO.

Risposte

1 akrun Aug 21 2020 at 03:43

Possiamo usare bind_rowsper legare gli listelementi e quindi fare un gruppo per operazione

library(dplyr)
bind_rows(dfs) %>% 
    group_by(exp, stage, section) %>% 
    summarise(across(everything(), ~ if(all(is.na(.))) NA_integer_ 
        else na.omit(.)))