簡體   English   中英

R 中帶有 NA 的日期列 - 變異的意外行為

[英]Date columns with NAs in R - unexpected behaviour with mutate

我正在嘗試使用數據集來遵循此過程。 這是一個測試數據框:

id <- c("Johnboy","Johnboy","Johnboy")
orderno <- c(2,2,1)
validorder <- c(0,1,1)
ordertype <- c(95,94,95)
orderdate <- as.Date(c("2019-06-17","2019-03-26","2018-08-23"))

df <- data.frame(id, orderno, validorder, ordertype, orderdate)

然后我執行以下操作:

## compute order date for order types
df <- df %>%
  mutate(orderdate_dried = if_else(validorder == 1 &
                                  ordertype == 95,
                                  orderdate, as.Date(NA)),
         orderdate_fresh = if_else(validorder == 1 &
                                  ordertype == 94,
                                  orderdate, as.Date(NA)))

## take minimum order date by type by order number
df <- df %>%
  group_by(id, orderno) %>%
  mutate(orderdate_dried = min(orderdate_dried, na.rm = TRUE),
         orderdate_fresh = min(orderdate_fresh, na.rm = TRUE)) %>%
  ungroup()

## aggregate order date for each type over individual
df <- df %>%
  group_by(id) %>%
  mutate(max_orderdate_dried = max(orderdate_dried, na.rm=TRUE),
         max_orderdate_fresh = max(orderdate_fresh, na.rm=TRUE)) %>%
  ungroup()

但是這個過程結束時的所有最大日期都是不適用的! 我不明白怎么辦? 此外,如果我為 NA 測試原始orderdate_dried

is.na(df$orderdate_dried)

我得到每一行的 NA! 這是怎么回事?!

非常有趣的問題,答案隱藏在問題本身中。 為了清楚起見,而不是每次我都會使用df1df2等時更新相同的df

讓我們首先從數據開始。

id <- c("Johnboy","Johnboy","Johnboy")
orderno <- c(2,2,1)
validorder <- c(0,1,1)
ordertype <- c(95,94,95)
orderdate <- as.Date(c("2019-06-17","2019-03-26","2018-08-23"))

df <- data.frame(id, orderno, validorder, ordertype, orderdate)

library(dplyr)

第1步 -

df1 <- df %>%
        mutate(orderdate_dried = if_else(validorder == 1 &
                                         ordertype == 95,
                                        orderdate, as.Date(NA)),
               orderdate_fresh = if_else(validorder == 1 &
                                         ordertype == 94,
                                         orderdate, as.Date(NA)))

df1
#       id orderno validorder ordertype  orderdate orderdate_dried orderdate_fresh
#1 Johnboy       2          0        95 2019-06-17            <NA>            <NA>
#2 Johnboy       2          1        94 2019-03-26            <NA>      2019-03-26
#3 Johnboy       1          1        95 2018-08-23      2018-08-23            <NA>

這里的一切都符合預期。

第2步 -

df2 <- df1 %>%
        group_by(id, orderno) %>%
        mutate(orderdate_dried = min(orderdate_dried, na.rm = TRUE),
                orderdate_fresh = min(orderdate_fresh, na.rm = TRUE)) %>%
        ungroup()

df2
# A tibble: 3 x 7
#  id      orderno validorder ordertype orderdate  orderdate_dried orderdate_fresh
#  <fct>     <dbl>      <dbl>     <dbl> <date>     <date>          <date>         
#1 Johnboy       2          0        95 2019-06-17 NA              2019-03-26     
#2 Johnboy       2          1        94 2019-03-26 NA              2019-03-26     
#3 Johnboy       1          1        95 2018-08-23 2018-08-23      NA           

這里的一切似乎也符合預期,當小組中沒有其他日期時,我們得到了NA

第 3 步 -

df3 <- df2 %>%
        group_by(id) %>%
        mutate(max_orderdate_dried = max(orderdate_dried, na.rm=TRUE),
               max_orderdate_fresh = max(orderdate_fresh, na.rm=TRUE)) %>%
         ungroup()

df3
# A tibble: 3 x 9
#  id      orderno validorder ordertype orderdate  orderdate_dried orderdate_fresh max_orderdate_dried max_orderdate_fresh
 #  <fct>     <dbl>      <dbl>     <dbl> <date>     <date>          <date>          <date>              <date>             
#1 Johnboy       2          0        95 2019-06-17 NA              2019-03-26      NA                  NA                 
#2 Johnboy       2          1        94 2019-03-26 NA              2019-03-26      NA                  NA                 
#3 Johnboy       1          1        95 2018-08-23 2018-08-23      NA              NA                  NA    

這里的一切似乎都錯了。 這些基本上與您已執行的步驟相同,這與您獲得的輸出相同,因此在此之前我們沒有做任何不同的事情。

我們錯過的一件事是在第 2 步中我們收到了一條警告消息。

警告消息: 1:在 min.default(c(NA_real_, NA_real_), na.rm = TRUE) :沒有非缺失的 min 參數; 返回 Inf 2:在 min.default(NA_real_, na.rm = TRUE) 中:沒有非缺失的 min 參數; 返回信息

因為我們在一個組中沒有非 NA 值,它返回Inf即使df2的輸出顯示 NA (為什么當值是Inf時它顯示NA在答案的末尾添加了對它的解釋)。 所以即使你用它測試is.na ,它is.na失敗。

is.na(df2$orderdate_dried)
#[1] FALSE FALSE FALSE

因此,帶有na.rm max na.rm失敗了。

 max(df2$orderdate_dried, na.rm = TRUE)
#[1] NA

因此,您將在步驟 3 中獲得所有NA


解決方案

解決方案是檢查is.finite

df3 <- df2 %>%
        group_by(id) %>%
         mutate(max_orderdate_dried = max(orderdate_dried[is.finite(orderdate_dried)], na.rm=TRUE),
                 max_orderdate_fresh = max(orderdate_fresh[is.finite(orderdate_fresh)], na.rm=TRUE)) %>%
         ungroup()


df3
# A tibble: 3 x 9
#  id      orderno validorder ordertype orderdate  orderdate_dried orderdate_fresh max_orderdate_dried max_orderdate_fresh
#  <fct>     <dbl>      <dbl>     <dbl> <date>     <date>          <date>          <date>              <date>             
#1 Johnboy       2          0        95 2019-06-17 NA              2019-03-26      2018-08-23          2019-03-26         
#2 Johnboy       2          1        94 2019-03-26 NA              2019-03-26      2018-08-23          2019-03-26         
#3 Johnboy       1          1        95 2018-08-23 2018-08-23      NA              2018-08-23          2019-03-26   

當值為Inf時,為什么將值顯示為NA

在第 2 步中,我們基本上要做的是

min(NA, na.rm = TRUE)
#[1] Inf

警告消息:在 min(NA, na.rm = TRUE) 中:沒有非缺失的 min 參數; 返回信息

這將返回帶有我們收到的警告的Inf

但是,由於我們知道一列只能保存一個class的值。

class(Inf) #is
#[1] "numeric"

但是我們在df1orderdate_dried列中有“Date”類的數據

 class(df1$orderdate_dried)
#[1] "Date"

所以Inf然后被強制轉換為返回的類“Date”。

as.Date(min(NA, na.rm = TRUE))
#[1] NA

這再次返回NA但它不是真正的NA並且is.na失敗了

is.na(as.Date(min(NA, na.rm = TRUE)))
#[1] FALSE

因此,第 3 步沒有按預期工作。

我希望這個答案是明確的,不要太混亂。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM