Eu tenho estes dados (desorganizados) contendo a fase do regime medicamentoso de cada paciente (ip ou cp), o nome do medicamento (codificado como um número) e informações sobre a dose para vários medicamentos:
df_have
# id ip_drug1 ip_dose1 ip_drug2 ip_dose2 cp_drug1 cp_dose1 cp_drug2 cp_dose2
# 1 A1 1 300 3 100 6 500 7 100
# 2 A2 1 300 2 200 11 300 NA NA
# 3 A3 1 500 NA NA 9 100 5 1500
Gostaria de deixar esses dados organizados e em formato longo:
df_want
# id phase drug dose
# 1 A1 ip 1 300
# 2 A1 ip 3 100
# 3 A1 cp 6 500
# 4 A1 cp 7 100
# 5 A2 ip 1 300
# 6 A2 ip 2 200
# 7 A2 cp 11 300
# 8 A2 cp NA NA
# 9 A3 ip 1 500
# 10 A3 ip NA NA
# 11 A3 cp 9 100
# 12 A3 cp 5 1500
Consegui obter o quadro de dados desejado com uma combinação de tidyr::pivot_longer
,, dplyr::mutate
e tidyr::pivot_wider
(e dplyr::select
):
library(tidyr)
library(dplyr)
df_have %>%
pivot_longer(cols = -id,
names_to = c("phase", "type"),
names_pattern = "(cp|ip)_(drug|dose)") %>%
mutate(temp = row_number(),
.by = c(id, phase, type)) %>%
pivot_wider(names_from = type,
values_from = value) %>%
select(-temp)
No entanto, o código de várias etapas acima é muito lento em meus dados reais muito grandes. Eu gostaria de realizar essa transformação mais rapidamente em tidyr
/ dplyr
, de preferência em uma única pivot_wider
etapa. Isso é possível?
Quadros reproduzíveis df_have
e df_want
de dados:
# have
df_have <- data.frame(id = paste0("A", 1:3),
ip_drug1 = 1,
ip_dose1 = c(300, 300, 500),
ip_drug2 = c(3, 2, NA),
ip_dose2 = c(100, 200, NA),
cp_drug1 = c(6, 11, 9),
cp_dose1 = c(500, 300, 100),
cp_drug2 = c(7, NA, 5),
cp_dose2 = c(100, NA, 1500))
# want
df_want <- data.frame(id = rep(paste0("A", 1:3), each = 4),
phase = rep(rep(c("ip", "cp"), each = 2), times = 3),
drug = c(1, 3, 6, 7, 1, 2, 11, NA, 1, NA, 9, 5),
dose = c(300, 100, 500, 100, 300, 200, 300, NA, 500, NA, 100, 1500))
É possível em uma única
pivot_longer
etapa. Isso deve ser cerca de 4,5x mais rápido:Acho que a chave é o uso de
.value
nonames_to
argumento. De?pivot_longer
:Referência
A solução de @ThomasIsCoding é ainda mais rápida (~ 12x)
Saída
Aqui está uma solução base R com um único
reshape
que dá