根据日期中的排名逐行选择值

MBB*_*MBB 9 r rank case-when dplyr

假设我有一个包含多行的数据框,如下所示:

df <- data.frame(a = c(NA,20,NA),
                 date1 = c("2016-03-01", "2016-02-01", "2016-02-01"),
                 b = c(50,NA, NA),
                 date2 = c("2016-02-01", "2016-03-01", "2016-03-01"),
                 c = c(10,10, 10),
                 date3 = c("2016-01-01","2016-01-01", "2016-01-01"))
Run Code Online (Sandbox Code Playgroud)

对于每一行,我想这不是一个最新的值NA之间a,b以及c根据dates(所以我分别来看看date1,date2或者date3和挑最近的一个).

基本上,date1给出对应于该值的日期a, date2给出对应于该值的日期b, date3给出对应于该值的日期c.

如果date1 > date2&date1 > date3,我将要取值a 但是,如果值aNA(在我的例子中是这种情况),我将比较date2date3.在我的例子中,date2 > date3由于价值b不是,NA50我将把50我的最终结果作为结果.

现在我想对我的数据帧中的所有行执行此操作

由于我使用的dplyr,我试着用case_when使用排序功能(在我的例子功能,我期待一个第一排日期,然后看看链接的值.如果是NA,我看最好排名第二等...)

但是,我不能像我想做的那样:

df <- df %>%
        mutate(result = case_when(is.na(a) & is.na(b) & is.na(c) ~ NA_integer_,
                                  rev(rank(date1, date2, date3))[1] == 3 & !is.na(a) ~ a,
                                  rev(rank(date1, date2, date3))[2] == 3 & !is.na(b) ~ b,
                                  rev(rank(date1, date2, date3))[3] == 3 & !is.na(a) ~ c,
                                  rev(rank(date1, date2, date3))[1] == 2 & !is.na(a) ~ a,
                                  rev(rank(date1, date2, date3))[2] == 2 & !is.na(b) ~ b,
                                  rev(rank(date1, date2, date3))[3] == 2 & !is.na(a) ~ c,
                                  rev(rank(date1, date2, date3))[1] == 1 & !is.na(a) ~ a,
                                  rev(rank(date1, date2, date3))[2] == 1 & !is.na(b) ~ b,
                                  rev(rank(date1, date2, date3))[3] == 1 & !is.na(a) ~ c))
Run Code Online (Sandbox Code Playgroud)

因为rank函数需要一个唯一的向量作为参数(但是我不能把c(date1, date2, date3)它放在一起因为它会给我这个向量的整个顺序而不是每行的等级)

在我的例子中,我希望得到的结果是

res

a    date1         b      date2       c    date3       result
NA   2016-03-01    50     2016-02-01  10   2016-01-01  50
20   2016-02-01    NA     2016-03-01  10   2016-01-01  20
NA   2016-02-01    NA     2016-03-01  10   2016-01-01  10
Run Code Online (Sandbox Code Playgroud)

有没有人对这个问题有任何想法甚至完全不同的方法?

tal*_*lat 4

我建议转换为长格式并计算相关值。如果需要,您可以将结果添加到原始 data.frame 中。以下是使用 data.table 执行此操作的方法:

library(data.table)
setDT(df)                     # convert to data.table object
df[, row := .I]               # add a row-id
dflong <- melt(df, id = "row", measure = patterns("^date", "^(a|b|c)"),
               na.rm = TRUE) # convert to long format
setorder(dflong, value1)      # reorder by date value
dflong <- unique(dflong, by = "row", fromLast = TRUE) # get the latest dates
df[dflong, result := i.value2, on = "row"]  # add result to original data

df
#    a      date1  b      date2  c      date3 row result
#1: NA 2016-03-01 50 2016-02-01 10 2016-01-01   1     50
#2: 20 2016-02-01 NA 2016-03-01 10 2016-01-01   2     20
#3: NA 2016-02-01 NA 2016-03-01 10 2016-01-01   3     10
Run Code Online (Sandbox Code Playgroud)