cumsum NA и другие условия R - PullRequest
       39

cumsum NA и другие условия R

2 голосов
/ 01 октября 2019

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

library(tidyverse)
library(lubridate)
df <- data.frame(group = c("a", "a", "a", "a", "a", "b", "b", "b"),
                 starts = c("2011-09-18", NA,  "2014-08-08", "2016-09-18", NA, "2013-08-08", "2015-08-08", NA),
                 ends = c(NA, "2013-03-06", "2015-08-08", NA, "2017-03-06", "2014-08-08", NA, "2016-08-08"))
df$starts <- parse_date_time(df$starts, "ymd")
df$ends <- parse_date_time(df$ends, "ymd")
df

  group     starts       ends
1     a 2011-09-18       <NA>
2     a       <NA> 2013-03-06
3     a 2014-08-08 2015-08-08
4     a 2016-09-18       <NA>
5     a       <NA> 2017-03-06
6     b 2013-08-08 2014-08-08
7     b 2015-08-08       <NA>
8     b       <NA> 2016-08-08

Желаемый результат:

  group     starts       ends epi
1     a 2011-09-18       <NA>   1
2     a       <NA> 2013-03-06   1
3     a 2014-08-08 2015-08-08   2
4     a 2016-09-18       <NA>   3
5     a       <NA> 2017-03-06   3
6     b 2013-08-08 2014-08-08   1
7     b 2015-08-08       <NA>   2
8     b       <NA> 2016-08-08   2

Я думал что-то подобное, но, очевидно, не учитывает эпизоды, где нет NA

df <- df %>% 
  group_by(group) %>% 
  mutate(epi = cumsum(is.na(ends)))
df

Я не уверен, как включить cumsum(is.na) с условием if_else. Может быть, я ошибаюсь?

Любые предложения будут великолепны.

Ответы [ 2 ]

4 голосов
/ 01 октября 2019

Решение с использованием dplyr. Предполагая, что ваш фрейм данных хорошо структурирован, каждый старт всегда имеет связанную конечную запись.

df2 <- df %>%
  group_by(group) %>%
  mutate(epi = cumsum(!is.na(starts))) %>%
  ungroup()
df2
# # A tibble: 8 x 4
#   group starts              ends                  epi
#   <fct> <dttm>              <dttm>              <int>
# 1 a     2011-09-18 00:00:00 NA                      1
# 2 a     NA                  2013-03-06 00:00:00     1
# 3 a     2014-08-08 00:00:00 2015-08-08 00:00:00     2
# 4 a     2016-09-18 00:00:00 NA                      3
# 5 a     NA                  2017-03-06 00:00:00     3
# 6 b     2013-08-08 00:00:00 2014-08-08 00:00:00     1
# 7 b     2015-08-08 00:00:00 NA                      2
# 8 b     NA                  2016-08-08 00:00:00     2
2 голосов
/ 01 октября 2019

Можно получить rowSums из NA элементов для столбцов 'начало', 'конец', сгруппированных по 'группе', получить rleid из 'epi'

library(dplyr)
library(data.table)
df %>% 
    mutate(epi =  rowSums(is.na(.[c("starts", "ends")]))) %>% 
    group_by(group) %>%
    mutate(epi = rleid(epi))
# A tibble: 8 x 4
# Groups:   group [2]
#  group starts              ends                  epi
#  <fct> <dttm>              <dttm>              <int>
#1 a     2011-09-18 00:00:00 NA                      1
#2 a     NA                  2013-03-06 00:00:00     1
#3 a     2014-08-08 00:00:00 2015-08-08 00:00:00     2
#4 a     2016-09-18 00:00:00 NA                      3
#5 a     NA                  2017-03-06 00:00:00     3
#6 b     2013-08-08 00:00:00 2014-08-08 00:00:00     1
#7 b     2015-08-08 00:00:00 NA                      2
#8 b     NA                  2016-08-08 00:00:00     2

Если есть только два столбца для рассмотрения

df %>% 
  group_by(group) %>%
  mutate(epi = rleid(is.na(starts) + is.na(ends)))
...