如何基于时间和现有变量创建新变量?

时间:2019-08-13 21:54:47

标签: r if-statement mutate

我有一个数据集,随着时间的推移,该数据集对多个人进行了重复测量。看起来像这样:

   ID           Time    Event      
   1   Jan 1 2012, 4pm    Abx            
   1   Jan 2 2012, 2pm   Test            
   1   Jan 26 2012 3 pm  Test            
   1  Jan 29 2012 10 pm   Abx            
   1  Jan 30 2012, 3 pm  Test            
   1    Jan 5 2012 3 pm  Test            
   2   Jan 1 2012, 4pm    Abx           
   2   Jan 2 2012, 2pm   Test            
   2   Jan 26 2012 3 pm  Test            

数据集当前基于事件。稍后将其过滤下来以进行测试。我需要做的是在测试的特定时间范围内发生某些事件(在这种情况下为Abx)时,将新变量设置为1。因此,如果事件“ Abx”在Test事件发生48小时之内发生,则新变量应等于1。否则,它应等于0。 我希望产生这样的东西:

   ID           Time    Event      New_variable
   1   Jan 1 2012, 4pm    Abx            1
   1   Jan 2 2012, 2pm   Test            1
   1   Jan 26 2012 3 pm  Test            0
   1  Jan 29 2012 10 pm   Abx            1
   1  Jan 30 2012, 3 pm  Test            1
   1    Jan 5 2012 3 pm  Test            0
   2   Jan 1 2012, 4pm    Abx            1
   2   Jan 2 2012, 2pm   Test            1
   2   Jan 26 2012 3 pm  Test            0

我知道我可以结合使用Dplyr mutate函数和ifelse语句来解决此问题,并且如果我只是想在发生抗生素事件时创建一个读取为“ 1”的变量,我可以这样做: / p>

 test %>%
   mutate(New_variable = ifelse(Event == 'Abx', 1, 0)) -> test2

但是我不知道如何计算时间,以便在Abx事件的48小时内测试事件= 1。我也不确定如何确保仅在同一ID中应用该条件。我该怎么办?

感谢您的帮助!

更新:非常感谢您的建议! 我将对数据进行尝试,但我认为它们会起作用。如果没有,我会很快回来。成功!我还修改了建议的辅助函数,以包括其他选项(适用于多种类型的Abx):

 abxRows <- type == "Abx" | type == "Abx2" 

2 个答案:

答案 0 :(得分:0)

所以我没有您的数据的副本,所以我不确定您的日期是多少……

我建议您使用as.POSIXct(Time, format="%b %d %Y, %I%p")将日期转换为正确的格式,有关该格式的更多信息,请查阅?strptime,但我认为这对您的专栏来说是正确的。

如果我们假设您的数据框是这样的...我知道我已经更改了部分内容,但这只是为了简单起见

df <- data.frame(ID = c(rep(1,6),rep(2,3)),
                 Time=c(seq(from=start, by=interval*6840, to=end)[1:6],seq(from=start, by=interval*6840, to=end)[1:3]),
                 Event = rep(c("Abs","Test","Test"),3))

这看起来像这样

  ID                Time Event
1  1 2012-01-01 00:00:00   Abs
2  1 2012-01-05 18:00:00  Test
3  1 2012-01-10 12:00:00  Test
4  1 2012-01-15 06:00:00   Abs
5  1 2012-01-20 00:00:00  Test
6  1 2012-01-24 18:00:00  Test
7  2 2012-01-01 00:00:00   Abs
8  2 2012-01-05 18:00:00  Test
9  2 2012-01-10 12:00:00  Test

因此,您可以使用以下代码测试Test到48小时内是否Abs落入

df[which(df$Event=="Test"),]$Time %in% unlist(Map(`:`, df[which(df$Event=="Abs"),]$Time-48*60*60, df[which(df$Event=="Abs"),]$Time+48*60*60))

因此这将对所有人返回FALSE,但这是因为综合数据的时间步长较大。

要打开包装... df[which(df$Event=="Test"),]$Time给出测试时间

%in%说的是在此之后的一组值中寻找在此之前的内容。

所以它是:unlist(Map(`:`, df[which(df$Event=="Abs"),]$Time-48*60*60, df[which(df$Event=="Abs"),]$Time+48*60*60)) 这将为每个Abs创建一个+/- 48小时的日期列表。加或减48小时,像POSIXct这样的对象在几秒钟内完成,因此48*60*60

答案 1 :(得分:0)

在提供的数据中,我添加了两个不应该是“ Abx”事件(即,一个不在48小时内的事件,另一个不在与48小时内的测试属于同一组的事件)。 / p>

library(dplyr)
library(lubridate)
library(purrr)

eventData <-
  data.frame(stringsAsFactors = FALSE,
             ID = c(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 1),
             Time = c("Jan 1 2012 4 pm", "Jan 2 2012, 2pm", 
                      "Jan 26 2012 3 pm", "Jan 29 2012 10 pm", 
                      "Jan 30 2012 3 pm", "Jan 5 2012 3 pm",
                      "Jan 1 2012 4 pm", "Jan 2 2012, 2pm",
                      "Jan 26 2012 3 pm", "Feb 12 2012 1pm",
                      "Jan 16 2012 3 pm", "Jan 16 2012 1 pm"),
             Event = c("Abx", "Test", "Test", "Abx", "Test", "Test", 
                       "Abx", "Test", "Test", "Abx", "Abx", "Test")
  ) %>%
  mutate(Time = mdy_h(Time),
         window = if_else(Event == "Test", 
                          interval(Time - hours(48), Time + hours(48)),
                          interval(NA, NA))
  )

首先,您要确保Time列是时间格式。然后创建一个lubridate时间间隔类的列,该列围绕“测试”事件创建一个48小时的窗口。

定义帮助程序功能,该功能将检查事件是否在窗口内发生。

chkFun <- function(eventTime, intervals, grp, type){

  abxRows <- type == "Abx"
  testRows <- !abxRows

  hits <- map2_lgl(eventTime, grp, 
                   ~any(.x %within% intervals[grp %in% .y], na.rm = TRUE)) &
    abxRows

  testHits <- map_lgl(which(testRows), 
                      ~any(eventTime[abxRows & (grp[.x] == grp)] %within% 
                             intervals[.x])) 

  hits[testRows] <- testHits

  as.integer(hits)

}

此功能首先通过并测试是否在间隔内发生“ Abx”事件。然后,它确定哪些“测试”行的间隔包含一个“ Abx”事件。该函数将这些强制转换的组合返回为整数。

最后,只需在helper函数中使用mutate语句,然后删除窗口列

eventData %>%
  mutate(New_variable = chkFun(Time, window, ID, Event)) %>%
  select(-window)

或者,辅助函数可以仅将data.frame作为参数并采用列名。但是,在上面的表格中,如果您首先在脚本中定义它,那么它也可以用在eventData

的原始定义中

结果:

#>    ID                Time Event New_variable
#> 1   1 2012-01-01 16:00:00   Abx            1
#> 2   1 2012-01-02 14:00:00  Test            1
#> 3   1 2012-01-26 15:00:00  Test            0
#> 4   1 2012-01-29 22:00:00   Abx            1
#> 5   1 2012-01-30 15:00:00  Test            1
#> 6   1 2012-01-05 15:00:00  Test            0
#> 7   2 2012-01-01 16:00:00   Abx            1
#> 8   2 2012-01-02 14:00:00  Test            1
#> 9   2 2012-01-26 15:00:00  Test            0
#> 10  2 2012-02-12 13:00:00   Abx            0
#> 11  2 2012-01-16 15:00:00   Abx            0
#> 12  1 2012-01-16 13:00:00  Test            0