【问题标题】:Creating a starting value variable with longitudinal data (conditional)使用纵向数据创建起始值变量(条件)
【发布时间】:2018-02-23 13:35:59
【问题描述】:

我正在尝试创建一个新变量,它基本上是我的数据框中另一个变量的起始值。示例数据:

id <- rep(c(1, 2), each = 8)
outcome <- rep(1:5, length.out = 16)
time <- rep(c(0, 1, 3, 4),4)
Attitude <- rep(c('A1', 'A2', 'A1', 'A2'), each = 4)
df <- data.frame(id, Attitude, outcome, time)

我想要得到的是一个名为 new_var(或其他)的新列,它等于 time == 0id = idoutcome 的值,并且还取决于 Attitude。因此,我想将dataframe 扩展为:

df$new_var <- c(1,1,1,1,5,5,5,5,4,4,4,4,3,3,3,3)

只有这样才能进行一些体面的编码。在 SAS 中,我知道我可以使用 lag 函数来做到这一点。我真的很感激一个不是“变通”的解决方案,所以它就像 SAS,而是正确的 r 解决方案。最后,我也想在 r 中变得更强大。

相关:Retain and lag function in R as SAS 但是,我更喜欢一些基于索引或“通常”r 方式的解决方案。在这里它也不依赖于其他条件。

因此,重要的是编码适用于不同的idsattitude 级别/变量(A1、A2、...),并且time == 0 处的outcome value 基本上复制到@987654334 @。

我希望我能清楚地传达我的信息。如果不是,我认为一小段示例代码以及我想如何扩展它应该足够清楚。期待建议。

编辑@jogo 答案的另一个示例代码。

ID <- rep(1, 36)
Attitude <- rep(c('A1', 'A2','A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'), 
length.out =36)
Answer_a <- rep(1:5, length.out = 36)
time <- as.character(rep(c(0, 1, 3, 4), each = 9))

df <- data.frame(ID, Attitude, Answer_a, time)
df$time <- as.character(df$time)

【问题讨论】:

    标签: r dataframe longitudinal


    【解决方案1】:

    我想这就是您的意思 - 假设数据总是按正确的顺序排列?

    编辑添加了排列步骤以确保数据始终正确排序。

            library(tidyverse)
            df %>% group_by(id, Attitude) %>% 
                   arrange(time) %>% 
                   mutate(new_var2 = first(outcome[!is.na(outcome)])
    
            # A tibble: 16 x 6
            # Groups:   id, Attitude [4]
                  id Attitude outcome  time new_var new_var2
               <dbl> <fct>      <int> <dbl>   <dbl>    <int>
             1  1.00 A1             1  0       1.00        1
             2  1.00 A1             2  1.00    1.00        1
             3  1.00 A1             3  3.00    1.00        1
             4  1.00 A1             4  4.00    1.00        1
             5  1.00 A2             5  0       5.00        5
             6  1.00 A2             1  1.00    5.00        5
             7  1.00 A2             2  3.00    5.00        5
             8  1.00 A2             3  4.00    5.00        5
             9  2.00 A1             4  0       4.00        4
            10  2.00 A1             5  1.00    4.00        4
            11  2.00 A1             1  3.00    4.00        4
            12  2.00 A1             2  4.00    4.00        4
            13  2.00 A2             3  0       3.00        3
            14  2.00 A2             4  1.00    3.00        3
            15  2.00 A2             5  3.00    3.00        3
            16  2.00 A2             1  4.00    3.00        3
    

    【讨论】:

    • 太棒了,这似乎有效!一个问题,只是为了确定。通过“假设数据始终处于正确的顺序”,您的意思是它由timeid 正确排序,对吗?还是它还取决于Attitude 的排序方式?将尽快对它是否确实有效进行更彻底的检查,但似乎有效。
    • 它使用如图所示的顺序来选择first(outcome)。您可以通过在group_bymutate 之间添加%&gt;% arrange(time) %&gt;% 来确保数据顺序正确
    • 感谢您的帮助。似乎是一个值得探索的包。
    • 您使用的是哪个包?试图获得更多信息。编辑:我意识到你加载了 tidyverse,但我想知道其中哪一个(因为似乎有很多安装它)。
    • 全部dplyr函数
    【解决方案2】:

    这是data.table的解决方案:

    library("data.table")
    setDT(df)
    df[, new_var:=outcome[1], rleid(Attitude)][]  # or
    # df[, new_var:=outcome[time==0], rleid(Attitude)][]
    

    为了测试,我将新列命名为new_var2

    id <- rep(c(1, 2), each = 8)
    outcome <- rep(1:5, length.out = 16)
    time <- rep(c(0, 1, 3, 4),4)
    Attitude <- rep(c('A1', 'A2', 'A1', 'A2'), each = 4)
    df <- data.frame(id, Attitude, outcome, time)
    df$new_var <- c(1,1,1,1,5,5,5,5,4,4,4,4,3,3,3,3)
    
    library("data.table")
    setDT(df)
    df[, new_var2:=outcome[1], rleid(Attitude)][] 
    # > df[, new_var2:=outcome[1], rleid(Attitude)][]
    #     id Attitude outcome time new_var new_var2
    #  1:  1       A1       1    0       1        1
    #  2:  1       A1       2    1       1        1
    #  3:  1       A1       3    3       1        1
    #  4:  1       A1       4    4       1        1
    #  5:  1       A2       5    0       5        5
    #  6:  1       A2       1    1       5        5
    #  7:  1       A2       2    3       5        5
    #  8:  1       A2       3    4       5        5
    #  9:  2       A1       4    0       4        4
    # 10:  2       A1       5    1       4        4
    # 11:  2       A1       1    3       4        4
    # 12:  2       A1       2    4       4        4
    # 13:  2       A2       3    0       3        3
    # 14:  2       A2       4    1       3        3
    # 15:  2       A2       5    3       3        3
    # 16:  2       A2       1    4       3        3
    

    您的第二个示例表明您必须对数据行重新排序。使用data.table这可以通过setkey()完成:

    ID <- rep(1, 36)
    Attitude <- rep(c('A1', 'A2','A3', 'A4', 'A5', 'A6', 'A7', 'A8', 'A9'), 
                    length.out =36)
    Answer_a <- rep(1:5, length.out = 36)
    time <- as.character(rep(c(0, 1, 3, 4), each = 9))
    
    df <- data.frame(ID, Attitude, Answer_a, time)
    df$time <- as.character(df$time)
    
    library("data.table")
    setDT(df)
    setkey(df, ID, Attitude, time)
    df[, new_var:=Answer_a[1], rleid(Attitude)]
    df
    

    【讨论】:

    • 由于某种原因,这似乎不适用于我正在使用的数据集。它只是在时间 0 复制答案,然后在时间 1 复制它,等等。所以它不会将 new_var's 的值修复为 time == 0time == 0time ==1 等。知道为什么会这样发生了什么?
    • 我编辑了答案 - 包括使用问题中的数据测试代码。如果您有此代码不起作用的数据,请在您的问题中举例说明。然后我可以修改代码。
    • 抱歉回复晚了,请参阅问题中的编辑以获取示例。请注意,我这里只有 1 个 ID,而在真实数据集中还有更多。但我认为这并不重要。
    • 这是重新排序数据的问题(类似于其他答案)。我将编辑我的答案。
    猜你喜欢
    • 2014-08-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-13
    • 2012-12-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多