【问题标题】:Create time axis for longitudinal data; calculations with data variables为纵向数据创建时间轴;使用数据变量进行计算
【发布时间】:2018-08-07 16:58:25
【问题描述】:

我有以下示例数据框。数据为长格式(纵向数据)。 col1 表示人员 ID(对于此示例,我们只有 2 个人)。 col2 表示生活事件的发生(例如 0 = 未婚,1 = 已婚)。状态从 0 到 1 的变化实际上标志着生命事件。对于事件之后的每个测量场合,col3 为 1,对于事件之前的每个测量场合,col3 为 0。年份表示评估年份。月份表示评估月份(02 = 二月)。

             col1   col2  col3  year   month

row.name11    A     0     0     2013   02
row.name12    A     0     0     2014   02
row.name13    A     1     1     2015   02
row.name14    A     0     1     2016   02
row.name15    A     0     1     2018   02
row.name16    B     0     0     2014   02
row.name17    B     0     0     2015   02
row.name18    B     1     1     2016   02
row.name19    B     0     1     2017   04

我现在希望创建一个以事件为中心的时间线。事件发生时新变量应为 0 (col2 == 1)。事件前为负数(表示事件发生前的月份),事件后为正数(表示事件发生后的月份)。

它应该看起来像这样(参见 event.time 变量):

             col1   col2  col3  year   month  event.time

row.name11    A     0     0     2013   02     -24
row.name12    A     0     0     2014   02     -12
row.name13    A     1     1     2015   02     0
row.name14    A     0     1     2016   02     12
row.name15    A     0     1     2018   02     36
row.name16    B     0     0     2014   02     -24
row.name17    B     0     0     2015   02     -12    
row.name18    B     1     1     2016   02     0
row.name19    B     0     1     2017   04     14

我发现我应该首先将我的年份和月份变量转换为日期变量(使用 as.date 函数)。然而,我没有成功。之后如何有效地计算 event.time 变量?也许使用 col3 因为这个变量表明它是在事件之前还是之后?

很高兴收到您的任何建议!在此先感谢:)

【问题讨论】:

    标签: r


    【解决方案1】:
    #if nchar(month) is 1 then add 0 before month, otherwise use month directly. 
    #1 added to make the transformation to as.Date simple
    df$date<- paste0(df$year,'-',ifelse(nchar(df$month)==1,paste0(0,df$month),df$month),'-1')
    df$date<- as.Date(df$date)
    
    library(dplyr)
    df %>% group_by(col1) %>% 
           #Get the minmume date where col2==1 incase there is more than one 1 in the same ID
           mutate(date_used=min(date[col2==1]), event.time=as.numeric(date - date_used))
    
    
    # A tibble: 9 x 8
    # Groups:   col1 [2]
    col1   col2  col3  year month date       date_used  event.time
    <fct> <int> <int> <int> <int> <date>     <date>          <dbl>
    1 A         0     0  2013     2 2013-02-01 2015-02-01       -730
    2 A         0     0  2014     2 2014-02-01 2015-02-01       -365
    3 A         1     1  2015     2 2015-02-01 2015-02-01          0
    4 A         0     1  2016     2 2016-02-01 2015-02-01        365
    5 A         0     1  2018     2 2018-02-01 2015-02-01       1096
    6 B         0     0  2014     2 2014-02-01 2016-02-01       -730
    7 B         0     0  2015     2 2015-02-01 2016-02-01       -365
    8 B         1     1  2016     2 2016-02-01 2016-02-01          0
    9 B         0     1  2017     4 2017-04-01 2016-02-01        425
    

    数据

    df <- read.table(text="
             col1   col2  col3  year   month
             row.name11    A     0     0     2013   02
             row.name12    A     0     0     2014   02
             row.name13    A     1     1     2015   02
             row.name14    A     0     1     2016   02
             row.name15    A     0     1     2018   02
             row.name16    B     0     0     2014   02
             row.name17    B     0     0     2015   02
             row.name18    B     1     1     2016   02
             row.name19    B     0     1     2017   04
                     ",header=T)
    

    【讨论】:

    • 您好,我使用示例数据尝试了您的代码。不幸的是,我得到了 date_used 列中所有行的“2015-02-01”,而不是获取 col2==1 的日期值(分别针对每组参与者)。知道可能出了什么问题吗?在此先感谢:)
    • 可能由于dplyrplyr 之间的名称冲突,group_by 没有按预期工作。尝试仅在新的 R 会话上加载 dplyr。或将group_by 明确称为dplyr::group_by
    【解决方案2】:

    这是一个使用lubridate的选项

    library(tidyverse)
    library(lubridate)
    ym <- function(y, m) ymd(sprintf("%s-%s-01", y, m))
    df %>%
        group_by(col1) %>%
        mutate(event.time = interval(ym(year, month)[col2 == 1], ym(year, month)) %/% months(1))
    ## A tibble: 9 x 6
    ## Groups:   col1 [2]
    #  col1   col2  col3  year month event.time
    #  <fct> <int> <int> <int> <int>      <dbl>
    #1 A         0     0  2013     2       -24.
    #2 A         0     0  2014     2       -12.
    #3 A         1     1  2015     2         0.
    #4 A         0     1  2016     2        12.
    #5 A         0     1  2018     2        36.
    #6 B         0     0  2014     2       -24.
    #7 B         0     0  2015     2       -12.
    #8 B         1     1  2016     2         0.
    #9 B         0     1  2017     4        14.
    

    样本数据

    df <- read.table(text =
        "             col1   col2  col3  year   month
    row.name11    A     0     0     2013   02
    row.name12    A     0     0     2014   02
    row.name13    A     1     1     2015   02
    row.name14    A     0     1     2016   02
    row.name15    A     0     1     2018   02
    row.name16    B     0     0     2014   02
    row.name17    B     0     0     2015   02
    row.name18    B     1     1     2016   02
    row.name19    B     0     1     2017   04", header = T)
    

    【讨论】:

    • 嗨 Maurits Evers,我今天早上尝试了你的代码,它运行良好(使用我自己的数据和这个示例数据)。但是,如果我现在尝试重现它,我会收到以下警告消息:注意:为函数“%/%”选择了签名为“Timespan#Timespan”的方法,目标签名为“Interval#Period”。 "Interval#ANY"、"ANY#Period" 也是有效的警告消息:1:在 as.numeric(end) - as.numeric(start) 中:较长的对象长度不是较短对象长度的倍数 2:在 unclass 中(e1) + unclass(e2) :较长的对象长度不是较短对象长度的倍数。任何想法为什么?
    • @MarieB。唔。听起来很奇怪。可以安全地忽略该注释。我无法重现警告。你能从一个新的 R 终端再次运行它吗?
    • 我做到了,不幸的是它似乎不能可靠地工作。即使我在新的 R 会话中使用完全相同的示例数据复制了相同的代码,event.time 变量也不准确。此评论选项不允许发布我现在拥有的 tibble。但对于上述样本数据,它的 c(-24, -24, 0, 0, 36, -24, 0, 0, 26) 。最让我恼火的是它昨天确实有效,但不再有效。通常这是一个用户问题,而不是 R 现在做的不同,但我不知道我做错了什么。
    • @MarieB。这似乎很奇怪。确保您没有加载任何其他包。如果您将上面的代码复制并粘贴到新的 R 终端中(确保不恢复已保存的工作区),则上面的代码必须有效。你能确认一下吗?
    猜你喜欢
    • 2019-11-24
    • 1970-01-01
    • 1970-01-01
    • 2023-01-11
    • 2012-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-16
    相关资源
    最近更新 更多