如何按日期而不是个人使处方数据框更宽
How to make prescription data frame wider in r by date, not by individual
我有长格式的患者处方数据,想创建一个更宽的数据框,其中每一行代表不同的处方交付。所以有些患者只有一排,但多次分娩的患者会有几排(每次处方分娩一排)。我以前只以非常简单的方式使用过 pivot 命令,但我很挣扎,因为我只为每个患者返回 1 行,而我想要为每个患者的每个处方交付日期返回 1 行。
我有一个非常简单的数据框,包含患者 ID、处方交付日期以及与他们收到的处方对应的代码。
id = id = factor(c("1001","1001","1001","1002","1002","1002","1002","1002","1003","1003"))
date = c("2013-10-31","2013-11-30","2013-12-31","2013-08-28","2013-08-28","2013-09-30",
"2013-09-30","2013-02-15","2013-02-15","2013-02-15")
atc_code = c("C07AA05","C07AA05","C07AA05","A10BA02","C09CA01","A10BA02",
"C09CA01","A10BA02","A10BA02","C07AA05")
date1 <- as.Date(date, format = "%Y-%m-%d")
df <- data.frame(id,
date1,
atc_code)
df
#> id date1 atc_code
#> 1 1001 2013-10-31 C07AA05
#> 2 1001 2013-11-30 C07AA05
#> 3 1001 2013-12-31 C07AA05
#> 4 1002 2013-08-28 A10BA02
#> 5 1002 2013-08-28 C09CA01
#> 6 1002 2013-09-30 A10BA02
#> 7 1002 2013-09-30 C09CA01
#> 8 1002 2013-02-15 A10BA02
#> 9 1003 2013-02-15 A10BA02
#> 10 1003 2013-02-15 C07AA05
Created on 2021-12-04 by the reprex package (v2.0.1)
我希望数据框看起来像什么:
df
#> id date atc_code_1 atc_code_2
#> 1 1001 2013-10-31 C07AA05 NA
#> 2 1001 2013-11-30 C07AA05 NA
#> 3 1001 2013-12-31 C07AA05 NA
#> 4 1002 2013-08-28 A10BA02 C09CA01
#> 5 1002 2013-09-30 A10BA02 C09CA01
#> 6 1002 2013-02-15 A10BA02 NA
#> 7 1003 2013-02-15 A10BA02 C07AA05
在现实中,一个病人一年可以分娩很多次,一次分娩可以开很多次处方,但我为了这个例子尽量简单。任何帮助将不胜感激。
我需要做的是创建一个带有变异(一种疾病)的新变量,该变量使用单次交付中的处方组合来定义(即患者是否获得了 x 和 y 处方,或者他们获得了 x 而不是 y处方),因此如果这可以通过一系列 group_bys 或其他方式实现,那也可以。
谢谢!
使用data.table:
(记录的顺序和你想要的不一样)
library(data.table)
setDT(df)
dcast(df, id + date1 ~ rowid(id, date1, prefix = 'atc_code_'),
value.var = 'atc_code')
id date1 atc_code_1 atc_code_2
1: 1001 2013-10-31 C07AA05 <NA>
2: 1001 2013-11-30 C07AA05 <NA>
3: 1001 2013-12-31 C07AA05 <NA>
4: 1002 2013-02-15 A10BA02 <NA>
5: 1002 2013-08-28 A10BA02 C09CA01
6: 1002 2013-09-30 A10BA02 C09CA01
7: 1003 2013-02-15 A10BA02 C07AA05
我想这就是你想要的:
library(tidyverse)
df <- df %>% group_by(id, date1) %>% mutate(num_scripts = row_number())
df_wide <- df %>% pivot_wider(names_from = num_scripts, values_from = atc_code)
编辑:更改了列名以匹配您的
df_wide <- df %>% pivot_wider(names_from = num_scripts, values_from = atc_code, names_prefix = "atc_code_")
考虑 ave
添加 运行 组计数 id
和 date1
分组,然后 reshape
宽。 (num
以下需要作为 ave
的临时变量,但可以使用任何数字字段。)
df <- within(df, {
atc_num <- ave(1:nrow(df), id, date1, FUN=seq_along)
}) |> reshape(
idvar = c("id", "date1"),
timevar = "atc_num",
direction = "wide"
)
df
id date1 atc_code.1 atc_code.2
1 1001 2013-10-31 C07AA05 <NA>
2 1001 2013-11-30 C07AA05 <NA>
3 1001 2013-12-31 C07AA05 <NA>
4 1002 2013-08-28 A10BA02 C09CA01
6 1002 2013-09-30 A10BA02 C09CA01
8 1002 2013-02-15 A10BA02 <NA>
9 1003 2013-02-15 A10BA02 C07AA05
您可以使用 tidyverse
。对于每个组(即 id
和 date1
),我们 mutate
一个新列来指定每个记录(我们将使用它来转向新列)。然后,您可以使用 pivot_wider
和 category
名称以及 atc_codes
来输入所需的格式。
library(tidyverse)
df %>%
dplyr::group_by(id, date1) %>%
dplyr::mutate(category = paste0("atc_code_", 1:n())) %>%
tidyr::pivot_wider(names_from = category, values_from = atc_code) %>%
dplyr::arrange(id, date1)
输出
# A tibble: 7 × 4
# Groups: id [3]
id date1 atc_code_1 atc_code_2
<fct> <date> <chr> <chr>
1 1001 2013-10-31 C07AA05 NA
2 1001 2013-11-30 C07AA05 NA
3 1001 2013-12-31 C07AA05 NA
4 1002 2013-02-15 A10BA02 NA
5 1002 2013-08-28 A10BA02 C09CA01
6 1002 2013-09-30 A10BA02 C09CA01
7 1003 2013-02-15 A10BA02 C07AA05
数据
df <- structure(
list(
id = structure(
c(1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L,
3L, 3L),
.Label = c("1001", "1002", "1003"),
class = "factor"
),
date1 = structure(
c(
16009, 16039, 16070, 15945, 15945, 15978, 15978,
15751, 15751, 15751
),
class = "Date"
),
atc_code = c(
"C07AA05", "C07AA05", "C07AA05", "A10BA02", "C09CA01",
"A10BA02", "C09CA01", "A10BA02", "A10BA02", "C07AA05"
)
),
class = "data.frame",
row.names = c(NA, -10L)
)
我有长格式的患者处方数据,想创建一个更宽的数据框,其中每一行代表不同的处方交付。所以有些患者只有一排,但多次分娩的患者会有几排(每次处方分娩一排)。我以前只以非常简单的方式使用过 pivot 命令,但我很挣扎,因为我只为每个患者返回 1 行,而我想要为每个患者的每个处方交付日期返回 1 行。
我有一个非常简单的数据框,包含患者 ID、处方交付日期以及与他们收到的处方对应的代码。
id = id = factor(c("1001","1001","1001","1002","1002","1002","1002","1002","1003","1003"))
date = c("2013-10-31","2013-11-30","2013-12-31","2013-08-28","2013-08-28","2013-09-30",
"2013-09-30","2013-02-15","2013-02-15","2013-02-15")
atc_code = c("C07AA05","C07AA05","C07AA05","A10BA02","C09CA01","A10BA02",
"C09CA01","A10BA02","A10BA02","C07AA05")
date1 <- as.Date(date, format = "%Y-%m-%d")
df <- data.frame(id,
date1,
atc_code)
df
#> id date1 atc_code
#> 1 1001 2013-10-31 C07AA05
#> 2 1001 2013-11-30 C07AA05
#> 3 1001 2013-12-31 C07AA05
#> 4 1002 2013-08-28 A10BA02
#> 5 1002 2013-08-28 C09CA01
#> 6 1002 2013-09-30 A10BA02
#> 7 1002 2013-09-30 C09CA01
#> 8 1002 2013-02-15 A10BA02
#> 9 1003 2013-02-15 A10BA02
#> 10 1003 2013-02-15 C07AA05
Created on 2021-12-04 by the reprex package (v2.0.1)
我希望数据框看起来像什么:
df
#> id date atc_code_1 atc_code_2
#> 1 1001 2013-10-31 C07AA05 NA
#> 2 1001 2013-11-30 C07AA05 NA
#> 3 1001 2013-12-31 C07AA05 NA
#> 4 1002 2013-08-28 A10BA02 C09CA01
#> 5 1002 2013-09-30 A10BA02 C09CA01
#> 6 1002 2013-02-15 A10BA02 NA
#> 7 1003 2013-02-15 A10BA02 C07AA05
在现实中,一个病人一年可以分娩很多次,一次分娩可以开很多次处方,但我为了这个例子尽量简单。任何帮助将不胜感激。
我需要做的是创建一个带有变异(一种疾病)的新变量,该变量使用单次交付中的处方组合来定义(即患者是否获得了 x 和 y 处方,或者他们获得了 x 而不是 y处方),因此如果这可以通过一系列 group_bys 或其他方式实现,那也可以。
谢谢!
使用data.table:
(记录的顺序和你想要的不一样)
library(data.table)
setDT(df)
dcast(df, id + date1 ~ rowid(id, date1, prefix = 'atc_code_'),
value.var = 'atc_code')
id date1 atc_code_1 atc_code_2
1: 1001 2013-10-31 C07AA05 <NA>
2: 1001 2013-11-30 C07AA05 <NA>
3: 1001 2013-12-31 C07AA05 <NA>
4: 1002 2013-02-15 A10BA02 <NA>
5: 1002 2013-08-28 A10BA02 C09CA01
6: 1002 2013-09-30 A10BA02 C09CA01
7: 1003 2013-02-15 A10BA02 C07AA05
我想这就是你想要的:
library(tidyverse)
df <- df %>% group_by(id, date1) %>% mutate(num_scripts = row_number())
df_wide <- df %>% pivot_wider(names_from = num_scripts, values_from = atc_code)
编辑:更改了列名以匹配您的
df_wide <- df %>% pivot_wider(names_from = num_scripts, values_from = atc_code, names_prefix = "atc_code_")
考虑 ave
添加 运行 组计数 id
和 date1
分组,然后 reshape
宽。 (num
以下需要作为 ave
的临时变量,但可以使用任何数字字段。)
df <- within(df, {
atc_num <- ave(1:nrow(df), id, date1, FUN=seq_along)
}) |> reshape(
idvar = c("id", "date1"),
timevar = "atc_num",
direction = "wide"
)
df
id date1 atc_code.1 atc_code.2
1 1001 2013-10-31 C07AA05 <NA>
2 1001 2013-11-30 C07AA05 <NA>
3 1001 2013-12-31 C07AA05 <NA>
4 1002 2013-08-28 A10BA02 C09CA01
6 1002 2013-09-30 A10BA02 C09CA01
8 1002 2013-02-15 A10BA02 <NA>
9 1003 2013-02-15 A10BA02 C07AA05
您可以使用 tidyverse
。对于每个组(即 id
和 date1
),我们 mutate
一个新列来指定每个记录(我们将使用它来转向新列)。然后,您可以使用 pivot_wider
和 category
名称以及 atc_codes
来输入所需的格式。
library(tidyverse)
df %>%
dplyr::group_by(id, date1) %>%
dplyr::mutate(category = paste0("atc_code_", 1:n())) %>%
tidyr::pivot_wider(names_from = category, values_from = atc_code) %>%
dplyr::arrange(id, date1)
输出
# A tibble: 7 × 4
# Groups: id [3]
id date1 atc_code_1 atc_code_2
<fct> <date> <chr> <chr>
1 1001 2013-10-31 C07AA05 NA
2 1001 2013-11-30 C07AA05 NA
3 1001 2013-12-31 C07AA05 NA
4 1002 2013-02-15 A10BA02 NA
5 1002 2013-08-28 A10BA02 C09CA01
6 1002 2013-09-30 A10BA02 C09CA01
7 1003 2013-02-15 A10BA02 C07AA05
数据
df <- structure(
list(
id = structure(
c(1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L,
3L, 3L),
.Label = c("1001", "1002", "1003"),
class = "factor"
),
date1 = structure(
c(
16009, 16039, 16070, 15945, 15945, 15978, 15978,
15751, 15751, 15751
),
class = "Date"
),
atc_code = c(
"C07AA05", "C07AA05", "C07AA05", "A10BA02", "C09CA01",
"A10BA02", "C09CA01", "A10BA02", "A10BA02", "C07AA05"
)
),
class = "data.frame",
row.names = c(NA, -10L)
)