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
但是,如果值a是NA(在我的例子中是这种情况),我将比较date2和date3.在我的例子中,date2 > date3由于价值b不是,NA但50我将把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)
有没有人对这个问题有任何想法甚至完全不同的方法?
我建议转换为长格式并计算相关值。如果需要,您可以将结果添加到原始 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)