使用纵向数据创建起始值变量(有条件的)
Creating a starting value variable with longitudinal data (conditional)
我正在尝试创建一个新变量,它基本上是我的数据框中另一个变量的起始值。示例数据:
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 == 0
处 id = id
的 outcome
的值并且还取决于 Attitude
。因此,我想将 dataframe
扩展为:
df$new_var <- c(1,1,1,1,5,5,5,5,4,4,4,4,3,3,3,3)
只有这样才能进行一些像样的编码。在 SAS 中,我知道我可以使用 lag
函数来做到这一点。我真的很感激不是 'work around' 的解决方案,所以它就像 SAS,而是正确的 r 解决方案。最后我也想在 r 方面变得更强。
相关:Retain and lag function in R as SAS
但是,我更喜欢一些基于索引或 'usual' r 方式的解决方案。在这里它也不依赖于其他条件。
因此,这里重要的是编码适用于不同的 ids
、attitude
级别/变量(A1、A2、...)并且 outcome value
在 time == 0
基本上是复制到 new_var
。
我希望我能清楚地传达我的信息。如果没有,我认为一小段示例代码以及我想如何扩展它应该足够清楚了。期待建议。
编辑 @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)
我想这就是您的意思 - 假设数据始终处于正确的顺序?
编辑 添加了一个排列步骤以确保数据始终正确排序。
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
这是 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
你的第二个例子表明你必须重新排序数据的行。 Usinf 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
我正在尝试创建一个新变量,它基本上是我的数据框中另一个变量的起始值。示例数据:
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 == 0
处 id = id
的 outcome
的值并且还取决于 Attitude
。因此,我想将 dataframe
扩展为:
df$new_var <- c(1,1,1,1,5,5,5,5,4,4,4,4,3,3,3,3)
只有这样才能进行一些像样的编码。在 SAS 中,我知道我可以使用 lag
函数来做到这一点。我真的很感激不是 'work around' 的解决方案,所以它就像 SAS,而是正确的 r 解决方案。最后我也想在 r 方面变得更强。
相关:Retain and lag function in R as SAS 但是,我更喜欢一些基于索引或 'usual' r 方式的解决方案。在这里它也不依赖于其他条件。
因此,这里重要的是编码适用于不同的 ids
、attitude
级别/变量(A1、A2、...)并且 outcome value
在 time == 0
基本上是复制到 new_var
。
我希望我能清楚地传达我的信息。如果没有,我认为一小段示例代码以及我想如何扩展它应该足够清楚了。期待建议。
编辑 @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)
我想这就是您的意思 - 假设数据始终处于正确的顺序?
编辑 添加了一个排列步骤以确保数据始终正确排序。
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
这是 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
你的第二个例子表明你必须重新排序数据的行。 Usinf 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