R: Gather/Spread/Reshape 21 Columns Based on 21 Other Column s
R: Gather/Spread/Reshape 21 Columns Based on 21 Other Column s
我想根据某些字段中的值创建列,并由其他字段中的值填充。例如 column1_time 的值为“1030”,column1_status 的值为 "booked"。我想将它们转换到一个新字段 time1030 中,值为 "booked." 有 21 个带有时间的唯一列(时间每行只列出一次,因此它们在 21 列中是唯一的)——并且有21 个独特的列,其状态映射回时间列。因此,这 42 个时间+状态列应重新排列为每个唯一时间的一列,并由该时间的相应状态填充。
我有这样的数据:
我想利用 R 的 gather/spread 或 reshape2(遗留)功能将此数据转置为如下所示:
我研究了 gather
和 spread
几个小时,但还是想不出来。我认为将键设置为 ends_with('_time')
并将值设置为 ends_with('_status')
可能会起作用,但我的尝试并没有起作用。
对于可重现的数据示例:
structure(list(appointment1_time = c("1030", "1030"), appointment2_time = c("1100",
"1100"), appointment3_time = c("1130", "1130"), appointment4_time = c("1200",
"1200"), appointment5_time = c("1230", "1230"), appointment6_time = c("0100",
"0100"), appointment7_time = c("0130", "0130"), appointment8_time = c("0200",
"0200"), appointment9_time = c("0230", "0230"), appointment10_time = c("0300",
"0300"), appointment11_time = c("0330", "0330"), appointment12_time = c("0400",
"0400"), appointment13_time = c("0430", "0430"), appointment14_time = c("0500",
"0500"), appointment15_time = c("0530", "0530"), appointment16_time = c("0600",
""), appointment17_time = c("0630", ""), appointment18_time = c("0700",
""), appointment19_time = c("0730", ""), appointment20_time = c(NA_character_,
NA_character_), appointment21_time = c(NA_character_, NA_character_
), appointment1_status = c("booked", "available"), appointment2_status = c("booked",
"available"), appointment3_status = c("booked", "available"),
appointment4_status = c("booked", "available"), appointment5_status = c("booked",
"available"), appointment6_status = c("booked", "available"
), appointment7_status = c("booked", "available"), appointment8_status = c("booked",
"available"), appointment9_status = c("booked", "available"
), appointment10_status = c("booked", "available"), appointment11_status = c("booked",
"available"), appointment12_status = c("available", "available"
), appointment13_status = c("available", "available"), appointment14_status = c("available",
"available"), appointment15_status = c("booked", "available"
), appointment16_status = c("available", ""), appointment17_status = c("available",
""), appointment18_status = c("available", ""), appointment19_status = c("available",
""), appointment20_status = c(NA_character_, NA_character_
), appointment21_status = c(NA_character_, NA_character_)), row.names = 1:2, class = "data.frame")
使用 tidyverse
的解决方案。
library(tidyverse)
# Get the time order
ord <- dat %>% select(ends_with("time")) %>% slice(1) %>% unlist()
# Remove NA
ord <- ord[!is.na(ord)]
dat2 <- dat %>%
rowid_to_column() %>%
gather(Column, Value, -rowid) %>%
separate(Column, into = c("Apt", "time/status"), sep = "_") %>%
spread(`time/status`, Value) %>%
# Remove NA or "" in the status column
filter(!is.na(status) & !status %in% "") %>%
mutate(Apt = str_c("apt_slot", time, sep = "_")) %>%
select(-time) %>%
spread(Apt, status) %>%
select(-rowid) %>%
# Reorder the column
select(str_c("apt_slot", ord, sep = "_"))
dat2
# apt_slot_1030 apt_slot_1100 apt_slot_1130 apt_slot_1200 apt_slot_1230 apt_slot_0100 apt_slot_0130
# 1 booked booked booked booked booked booked booked
# 2 available available available available available available available
# apt_slot_0200 apt_slot_0230 apt_slot_0300 apt_slot_0330 apt_slot_0400 apt_slot_0430 apt_slot_0500
# 1 booked booked booked booked available available available
# 2 available available available available available available available
# apt_slot_0530 apt_slot_0600 apt_slot_0630 apt_slot_0700 apt_slot_0730
# 1 booked available available available available
# 2 available <NA> <NA> <NA> <NA>
我想根据某些字段中的值创建列,并由其他字段中的值填充。例如 column1_time 的值为“1030”,column1_status 的值为 "booked"。我想将它们转换到一个新字段 time1030 中,值为 "booked." 有 21 个带有时间的唯一列(时间每行只列出一次,因此它们在 21 列中是唯一的)——并且有21 个独特的列,其状态映射回时间列。因此,这 42 个时间+状态列应重新排列为每个唯一时间的一列,并由该时间的相应状态填充。
我有这样的数据:
我想利用 R 的 gather/spread 或 reshape2(遗留)功能将此数据转置为如下所示:
我研究了 gather
和 spread
几个小时,但还是想不出来。我认为将键设置为 ends_with('_time')
并将值设置为 ends_with('_status')
可能会起作用,但我的尝试并没有起作用。
对于可重现的数据示例:
structure(list(appointment1_time = c("1030", "1030"), appointment2_time = c("1100",
"1100"), appointment3_time = c("1130", "1130"), appointment4_time = c("1200",
"1200"), appointment5_time = c("1230", "1230"), appointment6_time = c("0100",
"0100"), appointment7_time = c("0130", "0130"), appointment8_time = c("0200",
"0200"), appointment9_time = c("0230", "0230"), appointment10_time = c("0300",
"0300"), appointment11_time = c("0330", "0330"), appointment12_time = c("0400",
"0400"), appointment13_time = c("0430", "0430"), appointment14_time = c("0500",
"0500"), appointment15_time = c("0530", "0530"), appointment16_time = c("0600",
""), appointment17_time = c("0630", ""), appointment18_time = c("0700",
""), appointment19_time = c("0730", ""), appointment20_time = c(NA_character_,
NA_character_), appointment21_time = c(NA_character_, NA_character_
), appointment1_status = c("booked", "available"), appointment2_status = c("booked",
"available"), appointment3_status = c("booked", "available"),
appointment4_status = c("booked", "available"), appointment5_status = c("booked",
"available"), appointment6_status = c("booked", "available"
), appointment7_status = c("booked", "available"), appointment8_status = c("booked",
"available"), appointment9_status = c("booked", "available"
), appointment10_status = c("booked", "available"), appointment11_status = c("booked",
"available"), appointment12_status = c("available", "available"
), appointment13_status = c("available", "available"), appointment14_status = c("available",
"available"), appointment15_status = c("booked", "available"
), appointment16_status = c("available", ""), appointment17_status = c("available",
""), appointment18_status = c("available", ""), appointment19_status = c("available",
""), appointment20_status = c(NA_character_, NA_character_
), appointment21_status = c(NA_character_, NA_character_)), row.names = 1:2, class = "data.frame")
使用 tidyverse
的解决方案。
library(tidyverse)
# Get the time order
ord <- dat %>% select(ends_with("time")) %>% slice(1) %>% unlist()
# Remove NA
ord <- ord[!is.na(ord)]
dat2 <- dat %>%
rowid_to_column() %>%
gather(Column, Value, -rowid) %>%
separate(Column, into = c("Apt", "time/status"), sep = "_") %>%
spread(`time/status`, Value) %>%
# Remove NA or "" in the status column
filter(!is.na(status) & !status %in% "") %>%
mutate(Apt = str_c("apt_slot", time, sep = "_")) %>%
select(-time) %>%
spread(Apt, status) %>%
select(-rowid) %>%
# Reorder the column
select(str_c("apt_slot", ord, sep = "_"))
dat2
# apt_slot_1030 apt_slot_1100 apt_slot_1130 apt_slot_1200 apt_slot_1230 apt_slot_0100 apt_slot_0130
# 1 booked booked booked booked booked booked booked
# 2 available available available available available available available
# apt_slot_0200 apt_slot_0230 apt_slot_0300 apt_slot_0330 apt_slot_0400 apt_slot_0430 apt_slot_0500
# 1 booked booked booked booked available available available
# 2 available available available available available available available
# apt_slot_0530 apt_slot_0600 apt_slot_0630 apt_slot_0700 apt_slot_0730
# 1 booked available available available available
# 2 available <NA> <NA> <NA> <NA>