填写缺失的情况,直到每组具体情况
Fill in missing cases till specific condition per group
我正在尝试创建一个数据框,按主题显示我的数据集之间的所有月份。这是数据的示例:
dat <- data.frame(c(1, 1, 1, 2, 3, 3, 3, 4, 4, 4), c(rep(30, 2), rep(25, 5), rep(20, 3)), c('2017-01-01', '2017-02-01', '2017-04-01', '2017-02-01', '2017-01-01', '2017-02-01', '2017-03-01', '2017-01-01',
'2017-02-01', '2017-04-01'))
colnames(dat) <- c('id', 'value', 'date')
dat$Out.Of.Study <- c("", "", "Out", "Out", "", "", "Out", "", "", "Out")
dat
id value date Out.Of.Study
1 1 30 2017-01-01
2 1 30 2017-02-01
3 1 25 2017-04-01 Out
4 2 25 2017-02-01 Out
5 3 25 2017-01-01
6 3 25 2017-02-01
7 3 25 2017-03-01 Out
8 4 20 2017-01-01
9 4 20 2017-02-01
10 4 20 2017-04-01 Out
如果我想显示没有收集数据的月份之间(但受试者仍在研究中),我可以使用 complete()
函数。但是,问题是我根据数据集中标识的最小和最大月份获取每个主题 ID 的所有缺失月份:
## Add Dates by Group
library(tidyr)
complete(dat, id, date)
id date value Out.Of.Study
1 1 2017-01-01 30
2 1 2017-02-01 30
3 1 2017-03-01 NA <NA>
4 1 2017-04-01 25 Out
5 2 2017-01-01 NA <NA>
6 2 2017-02-01 25 Out
7 2 2017-03-01 NA <NA>
8 2 2017-04-01 NA <NA>
9 3 2017-01-01 25
10 3 2017-02-01 25
11 3 2017-03-01 25 Out
12 3 2017-04-01 NA <NA>
13 4 2017-01-01 20
14 4 2017-02-01 20
15 4 2017-03-01 NA <NA>
16 4 2017-04-01 20 Out
这个问题是我不希望缺失的月份超过受试者最后观察到的月份(基本上,我有受试者被审查并且需要从研究中删除)或出现在之前受试者开始研究的月份。例如,主题 2 只是“2017-02-01”月份的参与者。为此,我希望数据能够表示这是他们在那里的唯一月份,而不是用之后的额外月份和之前的额外月份来表示,如上所示。受试者3也是如此,虽然没有参加研究,但还有一个月的时间。
也许 complete()
不是解决此问题的最佳方法?
我仍然会使用 complete
(可能是此处使用的正确方法),但之后它会将超过行的行子集化为 "Out"
。您可以使用 dplyr::between
.
执行此操作
dat %>%
group_by(id) %>%
complete(date) %>%
# Filter rows that are between 1 and the one that has "Out"
filter(between(row_number(), 1, which(Out.Of.Study == "Out")))
id date value Out.Of.Study
<dbl> <fct> <dbl> <chr>
1 1 2017-01-01 30 ""
2 1 2017-02-01 30 ""
3 1 2017-03-01 NA NA
4 1 2017-04-01 25 Out
5 2 2017-01-01 NA NA
6 2 2017-02-01 25 Out
7 3 2017-01-01 25 ""
8 3 2017-02-01 25 ""
9 3 2017-03-01 25 Out
10 4 2017-01-01 20 ""
11 4 2017-02-01 20 ""
12 4 2017-03-01 NA NA
13 4 2017-04-01 20 Out
这可以通过为每个 id
单独创建一个月份序列并通过 dat
加入序列来完成缺失的月份来解决。
1。 data.table
(这个问题被标记为 tidyr
。但由于我对 data.table
更熟悉,所以我先尝试了这个。)
library(data.table)
# coerce date strings to class Date
setDT(dat)[, date := as.Date(date)]
# create sequence of months for each id
sdt <- dat[, .(date = seq(min(date), max(date), "month")), by = id]
# join
dat[sdt, on = .(id, date)]
id value date Out.Of.Study
1: 1 30 2017-01-01
2: 1 30 2017-02-01
3: 1 NA 2017-03-01 <NA>
4: 1 25 2017-04-01 Out
5: 2 25 2017-02-01 Out
6: 3 25 2017-01-01
7: 3 25 2017-02-01
8: 3 25 2017-03-01 Out
9: 4 20 2017-01-01
10: 4 20 2017-02-01
11: 4 NA 2017-03-01 <NA>
12: 4 20 2017-04-01 Out
请注意,根据 OP 的要求,id == 2
只有一行。
此方法需要将 date
从因子强制转换为 class Date
以确保完成所有缺失的月份。
这也比依赖数据集中可用的 date
因素更安全。为了便于说明,我们假设 id == 4
在月份 2017-06-01
(六月)而不是 2017-04-01
(四月)中是 Out
。那么整个数据集中就没有月份2017-05-01
(五月),最后的结果是不完整的
不创建临时变量 sdt
代码变为
library(data.table)
setDT(dat)[, date := as.Date(date)][
dat[, .(date = seq(min(date), max(date), "month")), by = id], on = .(id, date)]
2。 tidyr
/ dplyr
library(dplyr)
library(tidyr)
# coerce date strings to class Date
dat <- dat %>%
mutate(date = as.Date(date))
dat %>%
# create sequence of months for each id
group_by(id) %>%
expand(date = seq(min(date), max(date), "month")) %>%
# join to complete the missing month for each id
left_join(dat, by = c("id", "date"))
# A tibble: 12 x 4
# Groups: id [?]
id date value Out.Of.Study
<dbl> <date> <dbl> <chr>
1 1 2017-01-01 30 ""
2 1 2017-02-01 30 ""
3 1 2017-03-01 NA NA
4 1 2017-04-01 25 Out
5 2 2017-02-01 25 Out
6 3 2017-01-01 25 ""
7 3 2017-02-01 25 ""
8 3 2017-03-01 25 Out
9 4 2017-01-01 20 ""
10 4 2017-02-01 20 ""
11 4 2017-03-01 NA NA
12 4 2017-04-01 20 Out
有一个不更新的变体dat
:
library(dplyr)
library(tidyr)
dat %>%
mutate(date = as.Date(date)) %>%
right_join(group_by(., id) %>%
expand(date = seq(min(date), max(date), "month")),
by = c("id", "date"))
我正在尝试创建一个数据框,按主题显示我的数据集之间的所有月份。这是数据的示例:
dat <- data.frame(c(1, 1, 1, 2, 3, 3, 3, 4, 4, 4), c(rep(30, 2), rep(25, 5), rep(20, 3)), c('2017-01-01', '2017-02-01', '2017-04-01', '2017-02-01', '2017-01-01', '2017-02-01', '2017-03-01', '2017-01-01',
'2017-02-01', '2017-04-01'))
colnames(dat) <- c('id', 'value', 'date')
dat$Out.Of.Study <- c("", "", "Out", "Out", "", "", "Out", "", "", "Out")
dat
id value date Out.Of.Study
1 1 30 2017-01-01
2 1 30 2017-02-01
3 1 25 2017-04-01 Out
4 2 25 2017-02-01 Out
5 3 25 2017-01-01
6 3 25 2017-02-01
7 3 25 2017-03-01 Out
8 4 20 2017-01-01
9 4 20 2017-02-01
10 4 20 2017-04-01 Out
如果我想显示没有收集数据的月份之间(但受试者仍在研究中),我可以使用 complete()
函数。但是,问题是我根据数据集中标识的最小和最大月份获取每个主题 ID 的所有缺失月份:
## Add Dates by Group
library(tidyr)
complete(dat, id, date)
id date value Out.Of.Study
1 1 2017-01-01 30
2 1 2017-02-01 30
3 1 2017-03-01 NA <NA>
4 1 2017-04-01 25 Out
5 2 2017-01-01 NA <NA>
6 2 2017-02-01 25 Out
7 2 2017-03-01 NA <NA>
8 2 2017-04-01 NA <NA>
9 3 2017-01-01 25
10 3 2017-02-01 25
11 3 2017-03-01 25 Out
12 3 2017-04-01 NA <NA>
13 4 2017-01-01 20
14 4 2017-02-01 20
15 4 2017-03-01 NA <NA>
16 4 2017-04-01 20 Out
这个问题是我不希望缺失的月份超过受试者最后观察到的月份(基本上,我有受试者被审查并且需要从研究中删除)或出现在之前受试者开始研究的月份。例如,主题 2 只是“2017-02-01”月份的参与者。为此,我希望数据能够表示这是他们在那里的唯一月份,而不是用之后的额外月份和之前的额外月份来表示,如上所示。受试者3也是如此,虽然没有参加研究,但还有一个月的时间。
也许 complete()
不是解决此问题的最佳方法?
我仍然会使用 complete
(可能是此处使用的正确方法),但之后它会将超过行的行子集化为 "Out"
。您可以使用 dplyr::between
.
dat %>%
group_by(id) %>%
complete(date) %>%
# Filter rows that are between 1 and the one that has "Out"
filter(between(row_number(), 1, which(Out.Of.Study == "Out")))
id date value Out.Of.Study
<dbl> <fct> <dbl> <chr>
1 1 2017-01-01 30 ""
2 1 2017-02-01 30 ""
3 1 2017-03-01 NA NA
4 1 2017-04-01 25 Out
5 2 2017-01-01 NA NA
6 2 2017-02-01 25 Out
7 3 2017-01-01 25 ""
8 3 2017-02-01 25 ""
9 3 2017-03-01 25 Out
10 4 2017-01-01 20 ""
11 4 2017-02-01 20 ""
12 4 2017-03-01 NA NA
13 4 2017-04-01 20 Out
这可以通过为每个 id
单独创建一个月份序列并通过 dat
加入序列来完成缺失的月份来解决。
1。 data.table
(这个问题被标记为 tidyr
。但由于我对 data.table
更熟悉,所以我先尝试了这个。)
library(data.table)
# coerce date strings to class Date
setDT(dat)[, date := as.Date(date)]
# create sequence of months for each id
sdt <- dat[, .(date = seq(min(date), max(date), "month")), by = id]
# join
dat[sdt, on = .(id, date)]
id value date Out.Of.Study 1: 1 30 2017-01-01 2: 1 30 2017-02-01 3: 1 NA 2017-03-01 <NA> 4: 1 25 2017-04-01 Out 5: 2 25 2017-02-01 Out 6: 3 25 2017-01-01 7: 3 25 2017-02-01 8: 3 25 2017-03-01 Out 9: 4 20 2017-01-01 10: 4 20 2017-02-01 11: 4 NA 2017-03-01 <NA> 12: 4 20 2017-04-01 Out
请注意,根据 OP 的要求,id == 2
只有一行。
此方法需要将 date
从因子强制转换为 class Date
以确保完成所有缺失的月份。
这也比依赖数据集中可用的 date
因素更安全。为了便于说明,我们假设 id == 4
在月份 2017-06-01
(六月)而不是 2017-04-01
(四月)中是 Out
。那么整个数据集中就没有月份2017-05-01
(五月),最后的结果是不完整的
不创建临时变量 sdt
代码变为
library(data.table)
setDT(dat)[, date := as.Date(date)][
dat[, .(date = seq(min(date), max(date), "month")), by = id], on = .(id, date)]
2。 tidyr
/ dplyr
library(dplyr)
library(tidyr)
# coerce date strings to class Date
dat <- dat %>%
mutate(date = as.Date(date))
dat %>%
# create sequence of months for each id
group_by(id) %>%
expand(date = seq(min(date), max(date), "month")) %>%
# join to complete the missing month for each id
left_join(dat, by = c("id", "date"))
# A tibble: 12 x 4 # Groups: id [?] id date value Out.Of.Study <dbl> <date> <dbl> <chr> 1 1 2017-01-01 30 "" 2 1 2017-02-01 30 "" 3 1 2017-03-01 NA NA 4 1 2017-04-01 25 Out 5 2 2017-02-01 25 Out 6 3 2017-01-01 25 "" 7 3 2017-02-01 25 "" 8 3 2017-03-01 25 Out 9 4 2017-01-01 20 "" 10 4 2017-02-01 20 "" 11 4 2017-03-01 NA NA 12 4 2017-04-01 20 Out
有一个不更新的变体dat
:
library(dplyr)
library(tidyr)
dat %>%
mutate(date = as.Date(date)) %>%
right_join(group_by(., id) %>%
expand(date = seq(min(date), max(date), "month")),
by = c("id", "date"))