在R中的每一行中找到最早和最晚的日期

Find the earliest and latest date within each row in R

我有超过 400 列的大型数据集,这些列表示来自在线平台的某些用户输入元素以及每次输入发生的时间。每行代表一个用户 ID。

其中 200 列属于 class“POSIXct”“POSIXt”(例如 2019-11-04 15:33:50),并且可能会出现缺失值,因为并非每个元素都显示为或由每个用户填写。

我的目标是创建两个额外的列,其中包含这 200 个“POSIXct”“POSIXt”列中每行的最早和最晚日期。

这里是框架的简化示例和所需的附加列之一。 (ID 4 是一个从不费心打开侧面的人,但有来自其他数据源的数据可用,现在应该保留在数据集中)

ID Other_columns    date_column          date_column2          date_column3             max_date (what I want)
1  "numeric"        2019-11-04 19:33:50  2019-11-05 15:33:50   2019-11-05 16:33:50      2019-11-05 16:33:50
2  "numeric"        NA                   2019-11-04 17:20:10   2019-11-09 19:12:50      2019-11-09 19:12:50
3  "numeric"        2019-11-07 20:33:50  NA                    2019-11-04 18:31:50      2019-11-07 20:33:50
4  NA               NA                   NA                    NA                       NA

到目前为止,我并没有进一步过滤掉其他非日期列,

is.POSIXt <- function(x) inherits(x, "POSIXt")      
df%>%select(where(is.POSIXt))

而不是 select 我可能应该使用 mutate_at 或其他东西作为条件, 但是检查所有剩余的 200 date/time 列然后将 earliest/latest 日期分配给新创建的列(同时忽略 NA 值)的最佳方法是什么。

我们可以在 'date' 列上使用 pmaxpmin 来 return 每行的最早和最晚日期

library(dplyr)
 df %>%
     mutate(max_date = do.call(pmax, c(select(., starts_with('date')), na.rm = TRUE)),
            min_date = do.call(pmin, c(select(., starts_with('date')), 
         na.rm = TRUE)))
#  ID Other_columns         date_column        date_column2        date_column3            max_date            min_date
#1  1       numeric 2019-11-04 19:33:50 2019-11-05 15:33:50 2019-11-05 16:33:50 2019-11-05 16:33:50 2019-11-04 19:33:50
#2  2       numeric                <NA> 2019-11-04 17:20:10 2019-11-09 19:12:50 2019-11-09 19:12:50 2019-11-04 17:20:10
#3  3       numeric 2019-11-07 20:33:50                <NA> 2019-11-04 18:31:50 2019-11-07 20:33:50 2019-11-04 18:31:50
#4  4          <NA>                <NA>                <NA>                <NA>                <NA>                <NA>

rowwisec_across

的另一个选项
df %>% 
   rowwise() %>% 
   mutate(max_date =  max(as.POSIXct(c_across(starts_with('date'))), 
         na.rm = TRUE),
          min_date = min(as.POSIXct(c_across(starts_with('date'))), 
         na.rm = TRUE))

-输出

# A tibble: 4 x 7
# Rowwise: 
#     ID Other_columns date_column         date_column2        date_column3        max_date            min_date           
#  <int> <chr>         <chr>               <chr>               <chr>               <dttm>              <dttm>             
#1     1 numeric       2019-11-04 19:33:50 2019-11-05 15:33:50 2019-11-05 16:33:50 2019-11-05 16:33:50 2019-11-04 19:33:50
#2     2 numeric       <NA>                2019-11-04 17:20:10 2019-11-09 19:12:50 2019-11-09 19:12:50 2019-11-04 17:20:10
#3     3 numeric       2019-11-07 20:33:50 <NA>                2019-11-04 18:31:50 2019-11-07 20:33:50 2019-11-04 18:31:50
#4     4 <NA>          <NA>                <NA>                <NA>                NA NA               NA NA        

数据

df <- structure(list(ID = 1:4, Other_columns = c("numeric", "numeric", 
"numeric", NA), date_column = c("2019-11-04 19:33:50", NA, "2019-11-07 20:33:50", 
NA), date_column2 = c("2019-11-05 15:33:50", "2019-11-04 17:20:10", 
NA, NA), date_column3 = c("2019-11-05 16:33:50", "2019-11-09 19:12:50", 
"2019-11-04 18:31:50", NA)), class = "data.frame", row.names = c(NA, 
-4L))



  

这是另一种方法,您可以在不使用任何包的情况下使用。

首先,获取日期列的数据,然后您可以在每一行上使用 apply 函数来相应地获取最大值和最小值。这是示例:

df_date = df[, sapply(df, FUN = function(x) class(x)[1]) %in% c("POSIXct", "POSIXt")]
df$max = apply(df_date, 2, FUN = function(x) max(x, na.rm = TRUE)
df$min = apply(df_date, 2, FUN = function(x) min(x, na.rm = TRUE)

数据

structure(list(ID = 1:4, Other_columns = c("numeric", "numeric", 
"numeric", NA), date_column = structure(c(1572876230, NA, 1573139030, 
NA), class = c("POSIXct", "POSIXt"), tzone = ""), date_column2 = structure(c(1572948230, 
1572868210, NA, NA), class = c("POSIXct", "POSIXt"), tzone = ""), 
    date_column3 = structure(c(1572951830, 1573306970, 1572872510, 
    NA), class = c("POSIXct", "POSIXt"), tzone = "")), class = "data.frame", row.names = c(NA, 
-4L))