R 在另一个特定值之后标识值的出现
我有下表:R 在另一个特定值之后标识值的出现,r,date,data.table,dplyr,R,Date,Data.table,Dplyr,我有下表: +----+------------+----------+ | ID | Date | Variable | +----+------------+----------+ | a | 12/03/2017 | d | | a | 15/04/2017 | d | | a | 20/06/2017 | c | | b | 14/05/2017 | c | | b | 15/08/2017 | c
+----+------------+----------+
| ID | Date | Variable |
+----+------------+----------+
| a | 12/03/2017 | d |
| a | 15/04/2017 | d |
| a | 20/06/2017 | c |
| b | 14/05/2017 | c |
| b | 15/08/2017 | c |
| b | 16/09/2017 | c |
+----+------------+----------+
对于每个ID,我希望在单独的列中进行检查,检查在出现d值之后是否有c值,如下所示:
+----+------------+----------+-------+------------+
| ID | Date | Variable | Check | Date |
+----+------------+----------+-------+------------+
| a | 12/03/2017 | d | 1 | 20/06/2017 |
| a | 15/04/2017 | d | 1 | 20/06/2017 |
| a | 20/06/2017 | c | 1 | 20/06/2017 |
| b | 14/05/2017 | c | 0 | 0 |
| b | 15/08/2017 | c | 0 | 0 |
| b | 16/09/2017 | c | 0 | 0 |
+----+------------+----------+-------+------------+
这不仅仅是关于发现c的出现,而是关于看c是否出现在d之后。在单独的一栏中列出相应的日期也会有所帮助。我试着删除重复项&然后识别lead值或n行>1,但是有没有更简单的方法
任何dplyr或data.table方法都会非常有用。使用。肯定有比这更好的办法,但我认为这应该行得通。uniqueVariable[!is.naVariable]用于获取仅包含cc、d、cd、c、c或d的向量。如果你确定没有NA,你可以删除!是的。日期[变量%c][1]用于选择第一个日期
dat2 <- dat %>%
group_by(ID) %>%
mutate(Check = ifelse(identical(unique(Variable[!is.na(Variable)]), c("d", "c")),
1L, 0L)) %>%
mutate(Date2 = ifelse(Check == 1L, Date[Variable %in% "c"][1], "0")) %>%
ungroup()
dat2
# # A tibble: 6 x 5
# ID Date Variable Check Date2
# <chr> <chr> <chr> <int> <chr>
# 1 a 12/03/2017 d 1 20/06/2017
# 2 a 15/04/2017 d 1 20/06/2017
# 3 a 20/06/2017 c 1 20/06/2017
# 4 b 14/05/2017 c 0 0
# 5 b 15/08/2017 c 0 0
# 6 b 16/09/2017 c 0 0
资料
使用tidyr包装的填充物可以得到一种解决方案。方法如下: 首先为变量为C的行填充Check和C_Date。然后在Check和C_Date列上使用fill函数填充上面的行。此步骤将用d值填充行中的所需值。最后,对于变量为C的行,只需替换Check和C_Date的值 注意:OP建议检查变量为c的行可以是0或1。我的解决方案认为它是0 数据表解决方案。@RYoda还建议,您可以使用data.table::shift测试您的情况,然后将结果合并回原始数据集
check <- dat[, {
idx <- Variable =='d' & shift(Variable, type="lead") == "c"
list(MatchDate=ifelse(any(idx), shift(Date, type="lead", fill=NA_character_)[idx][1L], "0"),
Check=as.integer(any(idx)))
}, by=.(ID)]
dat[check, on=.(ID)]
# ID Date Variable MatchDate Check
# 1: a 12/03/2017 d 20/06/2017 1
# 2: a 15/04/2017 d 20/06/2017 1
# 3: a 20/06/2017 c 20/06/2017 1
# 4: b 14/05/2017 c 0 0
# 5: b 15/08/2017 c 0 0
# 6: b 16/09/2017 c 0 0
数据:
你的意思是检查c何时出现在d之后,以及检查d本身吗?因为这就是您期望的输出看起来的样子。变量列中只有c和d?如果d后面有多个c怎么办?你会在第二个日期栏报告哪一个日期?你希望第三行的支票是1吗?通过数据是领先还是滞后。我想,领先将是你最好的朋友。它将一列移动n行,然后您可以比较每一行d==c=>1…相同的基本思想:dat[,chk:=setDTshiftVariable,0:1[.c,d,on=.V1,V2,.n,nomatch=0]>0,by=ID]非常感谢,非常有用,我在您的答案和@www的答案之间犹豫了一下,但因为我需要它来进行教育,我决定使用dplyr,这对于R初学者来说通常更容易理解。没问题!也许一个好的研究项目是让他们比较tidyverse和data.TableThank-works&reads非常好,但是对于更大的数据集,我可能需要它,在这里,我对tidyr填充的经验是,它可能非常慢。@Psych91您对填充的看法完全正确,但我选择它是为了提供c和d多次出现/再次出现的灵活性。c_日期将从d之后第一次出现c开始。
# Data
df <- read.table(text = "ID Date Variable
a 12/03/2017 d
a 15/04/2017 d
a 20/06/2017 c
b 14/05/2017 c
b 15/08/2017 c
b 16/09/2017 c", header = T, stringsAsFactors = F)
df$Date <- as.POSIXct(df$Date, format = "%d/%m/%Y")
library(dplyr)
library(tidyr)
df %>% group_by(ID) %>%
arrange(ID, Date) %>%
mutate(Check = ifelse(Variable == "c", 1L, NA),
c_Date = ifelse(Variable == "c", as.character(Date), NA) ) %>%
fill(Check, .direction = "up") %>%
fill(c_Date, .direction = "up") %>%
mutate(Check = ifelse(Variable == "c", 0L, Check),
c_Date = ifelse(Variable == "c", NA, c_Date) )
# Result
# ID Date Variable Check c_Date
# <chr> <dttm> <chr> <int> <chr>
# 1 a 2017-03-12 00:00:00 d 1 2017-06-20
# 2 a 2017-04-15 00:00:00 d 1 2017-06-20
# 3 a 2017-06-20 00:00:00 c 0 <NA>
# 4 b 2017-05-14 00:00:00 c 0 <NA>
# 5 b 2017-08-15 00:00:00 c 0 <NA>
# 6 b 2017-09-16 00:00:00 c 0 <NA>
check <- dat[, {
idx <- Variable =='d' & shift(Variable, type="lead") == "c"
list(MatchDate=ifelse(any(idx), shift(Date, type="lead", fill=NA_character_)[idx][1L], "0"),
Check=as.integer(any(idx)))
}, by=.(ID)]
dat[check, on=.(ID)]
# ID Date Variable MatchDate Check
# 1: a 12/03/2017 d 20/06/2017 1
# 2: a 15/04/2017 d 20/06/2017 1
# 3: a 20/06/2017 c 20/06/2017 1
# 4: b 14/05/2017 c 0 0
# 5: b 15/08/2017 c 0 0
# 6: b 16/09/2017 c 0 0
library(data.table)
dat <- data.table(ID=rep(c('a','b'), each=3),
Date=c("12/03/2017","15/04/2017","20/06/2017","14/05/2017","15/08/2017","16/09/2017"),
Variable=c('d','d','c','c','c','c'))