выводить четверть столбца из месяца и месяц столбца из квартала - PullRequest
2 голосов
/ 01 апреля 2020

У меня есть список фреймов данных с одинаковыми именами столбцов, однако некоторые df имеют квартальную информацию, а другие - месячную. У некоторых есть оба или отсутствует оба. все фреймы данных имеют информацию о году. Я пытаюсь создать условие и получить недостающую информацию, чтобы наконец получить новые столбцы QtrYr и Date.

library(dplyr)
df <- dplyr::tibble(
  m = c(1, 2, NA, NA, NA, NA, 7, NA, 9, NA, NA, 12, NA),
  q = c(NA, NA, 1, 2, 2, 2, NA, 3, 3, 4, 4, 4, NA),
  y = c(2016, 2016, 2016, 2017, 2017, 2017, 2018 , 2018 , 2018 , 2020, 2020, 2020, 2020)
)
print(df)
#> # A tibble: 13 x 3
#>        m     q     y
#>    <dbl> <dbl> <dbl>
#>  1     1    NA  2016
#>  2     2    NA  2016
#>  3    NA     1  2016
#>  4    NA     2  2017
#>  5    NA     2  2017
#>  6    NA     2  2017
#>  7     7    NA  2018
#>  8    NA     3  2018
#>  9     9     3  2018
#> 10    NA     4  2020
#> 11    NA     4  2020
#> 12    12     4  2020
#> 13    NA    NA  2020

lsdf <- list(df1 = df, df2 = df)

желаемый выход.

out_df <- dplyr::tibble(
  m = c(1, 2, NA, NA, NA, NA, 7, NA, 9, NA, NA, 12, NA),
  q = c(NA, NA, 1, 2, 2, 2, NA, 3, 3, 4, 4, 4, NA),
  y = c(2016, 2016, 2016, 2017, 2019, 2020, 2017, 2019, 2020, 2016, 2017, 2019, 2020),
  qy = c("Q1/2016", "Q1/2016", "Q1/2016", "Q2/2017", "Q2/2017", "Q2/2017", "Q3/2018", "Q3/2018", "Q3/2018", "Q4/2020", "Q4/2020", "Q4/2020", NA),
  dy = c("3/1/2016", "3/1/2016", "3/1/2016", "6/1/2017", "6/1/2017", "6/1/2017", "9/1/2018", "9/1/2018", "9/1/2018", "12/1/2020", "12/1/2020", "12/1/2020", NA)
)

print(out_df)
#> # A tibble: 13 x 5
#>        m     q     y qy      dy       
#>    <dbl> <dbl> <dbl> <chr>   <chr>    
#>  1     1    NA  2016 Q1/2016 3/1/2016 
#>  2     2    NA  2016 Q1/2016 3/1/2016 
#>  3    NA     1  2016 Q1/2016 3/1/2016 
#>  4    NA     2  2017 Q2/2017 6/1/2017 
#>  5    NA     2  2019 Q2/2017 6/1/2017 
#>  6    NA     2  2020 Q2/2017 6/1/2017 
#>  7     7    NA  2017 Q3/2018 9/1/2018 
#>  8    NA     3  2019 Q3/2018 9/1/2018 
#>  9     9     3  2020 Q3/2018 9/1/2018 
#> 10    NA     4  2016 Q4/2020 12/1/2020
#> 11    NA     4  2017 Q4/2020 12/1/2020
#> 12    12     4  2019 Q4/2020 12/1/2020
#> 13    NA    NA  2020 <NA>    <NA>

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

lsdf$df1 %>% dplyr::mutate(
  Qrt = dplyr::case_when(
   is.na(m) & is.na(q) ~ NA,
   is.na(m) & !is.na(q) ~ q,
   m != NULL & q == NA ~ paste0("Q",ceiling(as.numeric(m)/3)),
   m != NULL & q != NULL ~ paste0("Q", q)
))
#> Error: `m != NULL & q == NA ~ paste0("Q", ceiling(as.numeric(m)/3))`, `m != NULL & q != NULL ~ paste0("Q", q)` must be length 13 or one, not 0

Создано в 2020-03-31 пакетом Представить (v0.3.0)

Думал, что могу получить Qtryear и затем запустите эту функцию zoo, чтобы получить дату.

 x <- c("Q1/13", "Q2/14")
as.Date(zoo::as.yearqtr(x, format = "Q%q/%y"))

Благодарим вас за помощь в решении этой проблемы.

Ответы [ 2 ]

1 голос
/ 01 апреля 2020

это то, что вы преследовали?

lsdf$df1 %>% 
  mutate(Qrt = case_when(
    !is.na(q) ~ q,
    !is.na(m) & is.na(q) ~ ceiling(as.numeric(m)/3),
    is.na(m) & is.na(q) ~ NA_real_
  )) %>%
  mutate(x = ifelse(is.na(Qrt), NA, paste0(Qrt, "/", y))) %>%
  mutate(x = as.Date(zoo::as.yearqtr(x, format = "%q/%y")))

Я немного прибрался в вашем деле. Проблема заключалась в том, что вы пытались объединить символьные и числовые значения c. Я изменил переменную Qrt на цифру c. Надеюсь, это поможет.

1 голос
/ 01 апреля 2020

case_when и if_else проверяют тип, поэтому все выходные данные условия должны быть одного типа. Также не ясно, почему NULL следует проверять на векторе ie. столбец как NULL будет автоматически удален и может существовать в list env

т.е.

c(NA, NULL, 1:3)
[1] NA  1  2  3

и

list(NULL, NULL, 1:3) 
#[[1]]
#NULL

#[[2]]
#NULL

#[[3]]
#[1] 1 2 3

Во втором case NULL останется таковым


Здесь, если мы выполняем проверки, используйте is.null вместе с is.na и убедитесь, что вывод получает один тип, q столбец numeric (преобразован в character), в то время как NA по умолчанию логичен (поэтому используйте NA_character_, поскольку при последнем выводе условия создается строка character с paste)

library(dplyr)
lsdf$df1 %>% dplyr::mutate(
   Qrt = dplyr::case_when(
    is.na(m) & is.na(q) ~ NA_character_,
    is.na(m) & !is.na(q) ~ as.character(q),
     !is.null(m) & !is.na(q) ~ paste0("Q",ceiling(as.numeric(m)/3)),
      !is.null(m) & !is.null(q) ~ paste0("Q", q)
 ))

Кроме того, поскольку это list, используйте map до l oop над list

library(purrr)
map(lsdf, ~ .x %>% dplyr::mutate(
   Qrt = dplyr::case_when(
    is.na(m) & is.na(q) ~ NA_character_,
    is.na(m) & !is.na(q) ~ as.character(q),
     !is.null(m) & !is.na(q) ~ paste0("Q",ceiling(as.numeric(m)/3)),
      !is.null(m) & !is.null(q) ~ paste0("Q", q)
 )))

Обновление

Если нам нужен столбец 'qy' как в обновленном

library(tidyr)
library(stringr)
library(zoo)
library(lubridate)
map(lsdf, ~ 
          .x %>%
              mutate(q1 = q) %>%
              fill(q, .direction = "downup") %>%
               mutate(qy = case_when(is.na(m) & is.na(q1) ~ NA_character_, 
                       TRUE ~ str_c("Q", q, "/", y))) %>%
               select(-q1)%>% 
               mutate(dy = floor_date(as.Date(as.yearqtr(qy, "Q%q/%Y"), frac = 1), "month"))))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...