J'ai cette trame de données:

> df
   date         val  cday
   <date>     <dbl> <dbl>
  2019-12-01     1     NA
  2019-12-02     0     NA
  2019-12-03     1     NA
  2019-12-04     0     1
  2019-12-05     0     NA
  2019-12-06     0     NA
  2019-12-07     1     1
  2019-12-08     2     NA
  2019-12-09     3     NA
  2019-12-10     3     NA
# … with 246 more rows

Je voudrais terminer df$cday en continu de df$cday == 1 à un maximum de 30 pour un suivant df$cday == 1 avant 30 Je veux recommencer à compter de 1 tous les autres NAs Je voudrais conserver.

Le résultat devrait ressembler à ceci:

> df
   date         val  cday
   <date>     <dbl> <dbl>
  2019-12-01     1     NA
  2019-12-02     0     NA
  2019-12-03     1     NA
  2019-12-04     0     1
  2019-12-05     0     2
  2019-12-06     0     3
  2019-12-07     1     1
  2019-12-08     2     2
  2019-12-09     3     3
  2019-12-10     3     4
# … with 246 more rows

Il existe probablement une solution simple à cela, mais je n'ai rien trouvé de recherche. Je serais très reconnaissant pour quelques conseils!

0
Näms 30 août 2020 à 20:05

2 réponses

Meilleure réponse

Une façon serait:

library(dplyr)

df %>%
  group_by(idx = cumsum(!is.na(cday))) %>%
  mutate(cday = case_when(!all(is.na(cday)) ~ row_number())) %>%
  ungroup %>% select(-idx)

Sortie (avec la partie visible de votre exemple):

# A tibble: 10 x 3
   date         val  cday
   <fct>      <int> <int>
 1 2019-12-01     1    NA
 2 2019-12-02     0    NA
 3 2019-12-03     1    NA
 4 2019-12-04     0     1
 5 2019-12-05     0     2
 6 2019-12-06     0     3
 7 2019-12-07     1     1
 8 2019-12-08     2     2
 9 2019-12-09     3     3
10 2019-12-10     3     4

Le code ci-dessus suppose que tous vos cas non manquants sont actuellement 1. Si les séquences peuvent également commencer par d'autres entiers, vous pouvez ajuster avec:

df %>%
  group_by(idx = cumsum(!is.na(cday))) %>%
  mutate(cday = case_when(!all(is.na(cday)) ~ cday[1] + (row_number() - 1))) %>%
  ungroup %>% select(-idx)
0
arg0naut91 30 août 2020 à 17:17

Nous pouvons utiliser rowid de data.table

library(dplyr)
library(data.table)
df %>% 
  mutate(cday = replace(rowid(cumsum(replace_na(cday, 0))), 
        seq_len(which.max(!is.na(cday))-1), NA))
#        date val cday
#1  2019-12-01   1   NA
#2  2019-12-02   0   NA
#3  2019-12-03   1   NA
#4  2019-12-04   0    1
#5  2019-12-05   0    2
#6  2019-12-06   0    3
#7  2019-12-07   1    1
#8  2019-12-08   2    2
#9  2019-12-09   3    3
#10 2019-12-10   3    4

Les données

df <- structure(list(date = c("2019-12-01", "2019-12-02", "2019-12-03", 
"2019-12-04", "2019-12-05", "2019-12-06", "2019-12-07", "2019-12-08", 
"2019-12-09", "2019-12-10"), val = c(1L, 0L, 1L, 0L, 0L, 0L, 
1L, 2L, 3L, 3L), cday = c(NA, NA, NA, 1L, NA, NA, 1L, NA, NA, 
NA)), class = "data.frame", row.names = c(NA, -10L))
0
akrun 30 août 2020 à 20:10