[英]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! 這是怎么回事?!
非常有趣的問題,答案隱藏在問題本身中。 為了清楚起見,而不是每次我都會使用df1
、 df2
等時更新相同的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"
但是我們在df1
的orderdate_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.