【问题标题】:lapply to find max value across rows not working as expectedlapply 查找未按预期工作的行的最大值
【发布时间】:2017-08-16 11:04:27
【问题描述】:

我正在尝试使用 lapply 跨行查找 data.table 的最大日期。我有一些行,其中行中的所有值都是NA,在这种情况下,我想返回一个特定的日期。我编写了一个函数来执行此操作,但没有得到预期的结果。

library(data.table)

my.max = function(x){
  if(all(is.na(x))){
    return(as.Date("9999-12-01")) #we can use this to identify which BPIDs have no end date
  }else{
    return(max(x, na.rm = T))
  }
}

DT = data.table("Date1" = c(as.Date("2015-12-30"),NA, NA), "Date2" = c(as.Date("2013-02-04"), as.Date("2014-01-01"), NA))
DT[ , "Row" := 1:.N]

DT[ , "Max_Date" := lapply(.SD, my.max), by = .(Row), .SDcols = c("Date1", "Date2")]

返回

> DT
        Date1      Date2 Row   Max_Date
1: 2015-12-30 2013-02-04   1 2015-12-30
2:       <NA> 2014-01-01   2 9999-12-01
3:       <NA>       <NA>   3 9999-12-01

因此,如果所有值都是NA,它确实有效,但如果其中一个值是NA,它也会返回9999-12-01。我将打印函数放入my.max 以了解发生了什么,看起来它一次传入一个 x 值。这解释了为什么 all(is.na(x)) 会是真的,但我希望它会传入行中两个日期的向量。否则,它怎么知道取最大值的值是多少?

如何更改我的函数,使其仅在其他两个日期均为 NA 时才返回 9999-12-01

【问题讨论】:

    标签: r data.table lapply


    【解决方案1】:

    这是一种可行的方法。它将{}中的多条语句封装成一个单独的代码块:

    DT[, "this" := {temp=pmax(Date1, Date2, na.rm=TRUE);
                    temp[is.na(temp)] = as.Date("9999-12-01"); temp}]
    

    返回

    DT
            Date1      Date2       this
    1: 2015-12-30 2013-02-04 2015-12-30
    2:       <NA> 2014-01-01 2014-01-01
    3:       <NA>       <NA> 9999-12-01
    

    数据

    DT = data.table("Date1" = c(as.Date("2015-12-30"),NA, NA),
                    "Date2" = c(as.Date("2013-02-04"), as.Date("2014-01-01"), NA))
    

    这样,您不必遍历可能非常慢的每一行。


    虽然我不推荐按行处理...

    DT[ , "Row" := 1:.N]
    DT[ , "Max_Date" := my.max(unlist(.SD)), by = .(Row), .SDcols = c("Date1", "Date2")]
    

    对于本示例将产生相同的输出。

    【讨论】:

    • 感谢您的回复。我想如果可能的话,我更愿意用 lapply 来做这件事,因为我可能需要在以后为最大日期添加更多过滤。有没有办法让你知道的工作?
    【解决方案2】:

    试试这个:

    library(data.table)
    
    my.max <- function(x){
        if(all(is.na(x))){
            return("9999-12-01") 
        }else{
            return(max(x, na.rm = T))
        }
    }
    
    DT <- data.table("Date1" = c(as.Date("2015-12-30"),NA, NA), "Date2" = c(as.Date("2013-02-04"), as.Date("2014-01-01"), NA))
    print(DT)
    DT[ , "Max_Date" ] <- apply(DT, 1, my.max)
    print(DT)
    
    
    
    > DT <- data.table("Date1" = c(as.Date("2015-12-30"),NA, NA), "Date2" = c(as.Date("2013-02-04"), as.Date("2014-01-01"), NA))
    > print(DT)
            Date1      Date2
    1: 2015-12-30 2013-02-04
    2:       <NA> 2014-01-01
    3:       <NA>       <NA>
    > DT[ , "Max_Date" ] <- apply(DT, 1, my.max)
    > print(DT)
            Date1      Date2   Max_Date
    1: 2015-12-30 2013-02-04 2015-12-30
    2:       <NA> 2014-01-01 2014-01-01
    3:       <NA>       <NA> 9999-12-01
    

    【讨论】:

    • 顺便说一句,我忘记包含 DT[ , "Row" := 1:.N] 但您可以将其添加回原来帖子中的相同位置,您会想要您正在寻找仍然
    • 感谢您的回复。我不喜欢使用 apply ,因为它首先将其转换为矩阵,所以相当慢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-13
    • 1970-01-01
    • 2015-02-14
    • 2015-09-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多