按条件从长格式数据集中提取特定行/采用长格式数据进行生存分析
Extracting specific rows from long format dataset by conditions / adopting long format data to survival analysis
背景:
我有一个正在准备用于生存分析的数据集,它最初是一个长格式的纵向数据集。我有一个分隔参与者的 ID 变量、一个时间变量(月)和我的二进制 0/1 事件变量(是否有人在赌博时达到“每月损失限额”)。
Problem/goal:
我正在尝试为生存分析创建必要的变量,然后删除 excess/unnecessary 行。在整个研究期间,我的事件(达到损失限额)在技术上可以为每个参与者多次发生,但我只对参与者的第一次发生感兴趣。我制作了一个持续时间变量并尝试使用 if-else 语句对其进行修改,以便满足损失限制的参与者将该特定月份作为他们的终点。
问题是我似乎无法以只保留所需行的方式进行过滤。我尝试了一些带有 if-else 语句的代码,但出现错误。 对于满足一个或多个损失限制的参与者,我想提取满足其第一个损失限制的行,因为修改后的持续时间也包含在该行中。对于从未达到损失限额的参与者我无所谓,任何行都可以,因为他们都有必要的信息。
我该如何完成?
示例数据框和代码:
library(dplyr)
# Example variables and data frame in long form
# Includes id variable, time variable and example event variable
id <- c(1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3 )
time <- c(2, 3, 4, 7, 3, 5, 7, 1, 2, 3, 4, 5)
metLimit <- c(0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1)
dfLong <- data.frame(id = id, time = time, metLimit = metLimit)
# Making variables, time at start, finish and duration variable
dfLong <- dfLong %>%
group_by(id) %>%
mutate(startTime = first(time),
lastTime = last(time))
dfLong <- dfLong %>%
group_by(id) %>%
mutate(timeDuration = ifelse(metLimit == "1", c(time - startTime),
lastTime - startTime))
# My failed attempt at solving the problem
dfLong <- dfLong %>%
group_by(id) %>%
ifelse(metLimit == "1", filter(first(metLimit)), filter(last(time)
您可以对 idgroups 进行排序:
dfLong %>%
group_by(id) %>%
arrange(desc(metLimit),time,.by_group=TRUE) %>%
# This one is critical, order by metlimit descending first
# (MetLimit==1 will be in the first rows of the group if it exists for this
# particular id) then order by time:
# Within every Group of id,MeTlimit , put the lowest tim in the upper row
# of the id Group
slice_head(n=1) # get the first row for each id-group
这导致:
# A tibble: 3 x 6
# Groups: id [3]
id time metLimit startTime lastTime timeDuration
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 2 0 2 7 5
2 2 5 1 3 7 2
3 3 2 1 1 5 1
因为你不关心从未达到极限的参与者的样本点,这应该足够了。
如何将最后一步替换为:
dfLong <- dfLong %>%
group_by(id) %>%
dplyr::filter(metLimit == ifelse(sum(metLimit), 1, 0)) %>%
dplyr::slice_head(n = 1)
> # A tibble: 3 x 6
> # Groups: id [3]
> id time metLimit startTime lastTime timeDuration
> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
> 1 1 2 0 2 7 5
> 2 2 5 1 3 7 2
> 3 3 2 1 1 5 1
filter()
步骤获取 metLimit
为 1 的行,除非它们全为 0(sum == 0 == false)。然后你得到第一行。
背景:
我有一个正在准备用于生存分析的数据集,它最初是一个长格式的纵向数据集。我有一个分隔参与者的 ID 变量、一个时间变量(月)和我的二进制 0/1 事件变量(是否有人在赌博时达到“每月损失限额”)。
Problem/goal:
我正在尝试为生存分析创建必要的变量,然后删除 excess/unnecessary 行。在整个研究期间,我的事件(达到损失限额)在技术上可以为每个参与者多次发生,但我只对参与者的第一次发生感兴趣。我制作了一个持续时间变量并尝试使用 if-else 语句对其进行修改,以便满足损失限制的参与者将该特定月份作为他们的终点。
问题是我似乎无法以只保留所需行的方式进行过滤。我尝试了一些带有 if-else 语句的代码,但出现错误。 对于满足一个或多个损失限制的参与者,我想提取满足其第一个损失限制的行,因为修改后的持续时间也包含在该行中。对于从未达到损失限额的参与者我无所谓,任何行都可以,因为他们都有必要的信息。
我该如何完成?
示例数据框和代码:
library(dplyr)
# Example variables and data frame in long form
# Includes id variable, time variable and example event variable
id <- c(1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3 )
time <- c(2, 3, 4, 7, 3, 5, 7, 1, 2, 3, 4, 5)
metLimit <- c(0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1)
dfLong <- data.frame(id = id, time = time, metLimit = metLimit)
# Making variables, time at start, finish and duration variable
dfLong <- dfLong %>%
group_by(id) %>%
mutate(startTime = first(time),
lastTime = last(time))
dfLong <- dfLong %>%
group_by(id) %>%
mutate(timeDuration = ifelse(metLimit == "1", c(time - startTime),
lastTime - startTime))
# My failed attempt at solving the problem
dfLong <- dfLong %>%
group_by(id) %>%
ifelse(metLimit == "1", filter(first(metLimit)), filter(last(time)
您可以对 idgroups 进行排序:
dfLong %>%
group_by(id) %>%
arrange(desc(metLimit),time,.by_group=TRUE) %>%
# This one is critical, order by metlimit descending first
# (MetLimit==1 will be in the first rows of the group if it exists for this
# particular id) then order by time:
# Within every Group of id,MeTlimit , put the lowest tim in the upper row
# of the id Group
slice_head(n=1) # get the first row for each id-group
这导致:
# A tibble: 3 x 6
# Groups: id [3]
id time metLimit startTime lastTime timeDuration
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 1 2 0 2 7 5
2 2 5 1 3 7 2
3 3 2 1 1 5 1
因为你不关心从未达到极限的参与者的样本点,这应该足够了。
如何将最后一步替换为:
dfLong <- dfLong %>%
group_by(id) %>%
dplyr::filter(metLimit == ifelse(sum(metLimit), 1, 0)) %>%
dplyr::slice_head(n = 1)
> # A tibble: 3 x 6
> # Groups: id [3]
> id time metLimit startTime lastTime timeDuration
> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
> 1 1 2 0 2 7 5
> 2 2 5 1 3 7 2
> 3 3 2 1 1 5 1
filter()
步骤获取 metLimit
为 1 的行,除非它们全为 0(sum == 0 == false)。然后你得到第一行。