Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 在另一个特定值之后标识值的出现_R_Date_Data.table_Dplyr - Fatal编程技术网

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'))