【问题标题】:infer quarter column from month and month column from quarter从月推断季度列,从季度推断月列
【发布时间】:2020-07-12 13:47:22
【问题描述】:

我有一个具有相同列名的数据框列表,但是一些 df 有季度信息,而其他有月份信息。有些人两者都有或两者都没有。所有数据框都有年份信息。我正在尝试建立一个条件并得出缺失的信息,以最终获得新列QtrYrDate

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

reprex package (v0.3.0) 于 2020 年 3 月 31 日创建

我想我可以得到一个 Qtryear 列,然后运行这个 zoo 函数来获取日期。

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

感谢您对解决此问题的任何帮助。

【问题讨论】:

  • 我认为你需要is.nullis.na
  • case_when 中的T 是什么
  • 只是添加 TRUE,但可能是 NA
  • 它不起作用,因为case_when 需要对所有输出案例具有相同的类型。在第二个表达式中,它是来自 q 的 dbl,然后你正在做paste,即字符

标签: r dplyr tidyverse lapply purrr


【解决方案1】:

case_whenif_else 会进行类型检查,因此所有条件输出都必须是相同类型。另外,不清楚为什么应该在向量上检查NULL,即。 NULL 的列将被自动删除,它可以存在于 list 环境中

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

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

#[[2]]
#NULL

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

在第二种情况下,NULL 将保持原样


在这里,如果我们进行检查,请使用 is.nullis.na,并确保输出为单一类型,q 列是 numeric(转换为 character)而 @ 987654334@ 默认是逻辑的(所以使用NA_character_,因为最后一个条件输出会创建一个带有pastecharacter 字符串)

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 来循环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"))))

【讨论】:

  • 非常感谢
【解决方案2】:

这就是你想要的吗?

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")))

我清理了你的案子_当一点点。问题是您试图组合字符和数字输出。我已将 Qrt 变量更改为数字。希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-11-16
    • 2014-09-23
    • 2021-01-07
    • 2018-08-30
    • 2014-12-13
    • 2020-03-26
    • 1970-01-01
    • 2014-07-03
    相关资源
    最近更新 更多