Очень интересный вопрос и ответ кроется в самом вопросе. Для ясности вместо обновления одного и того же df
каждый раз я буду использовать df1
, df2
et c.
Давайте сначала начнем с данных.
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; возвращая Inf
Поскольку в группе не было значения, отличного от NA, он вернул Inf
, хотя вывод df2
показывает NA (почему он показывает NA
, когда значение Inf
добавил пояснения к нему в конце ответа). Так что даже если вы протестируете is.na
с ним, это не удастся.
is.na(df2$orderdate_dried)
#[1] FALSE FALSE FALSE
Следовательно, max
с na.rm
тоже дает сбой.
max(df2$orderdate_dried, na.rm = TRUE)
#[1] NA
Следовательно, вы получаете все NA
с на шаге 3.
Решение
Решение состоит в том, чтобы проверить с помощью 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
Почему он показывает значение как NA
, когда значение равно Inf
?
На шаге 2, что мы в основном делают это
min(NA, na.rm = TRUE)
#[1] Inf
Предупреждение: в мин. (NA, na.rm = TRUE): нет не пропущенных аргументов для min; возвращая Inf
Возвращает Inf
с предупреждением, которое мы получаем.
Однако, поскольку мы знаем, что столбец может содержать значение только одного class
.
class(Inf) #is
#[1] "numeric"
, но у нас есть данные класса "Date" в столбце df1
orderdate_dried
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 не работает должным образом ,
Надеюсь, этот ответ ясен и не слишком запутан.