Return 列标题介于两个日期之间时的值
Return value if column heading falls between two dates
我有两个数据帧 ID_list
和 Attendance
:
ID_list
包含唯一 ID 的列表、他们的出生日期和他们生命中随后几年的生日
ID DOB Y1 Y2 Y3
1 01/05/2003 01/05/2004 01/05/2005 01/05/2006
2 05/02/2010 05/02/2011 05/02/2012 05/02/2013
3 17/06/2015 17/06/2016 17/06/2017 17/06/2018
Attendance
包含一个 ID 列表,其中一些与 ID_list
中的 ID 和不同日期的出席率数字相匹配:
ID 01/07/2010 01/07/2011 01/07/2012
4 100% 50% 75%
2 60% 40% 30%
6 80% 60% 100%
我想生成一个新的数据框,其中包含 ID 列表及其生命中每一年的出勤率,其中 Attendance
数据框中列标题中指定的日期介于两个之间ID_List
数据框中的日期。基于上面的示例,它看起来像这样:
ID Y1_att Y2_att Y3_att
1 NA NA NA
2 60% 40% 30%
3 NA NA NA
我一直在尝试使用 %within%
和 interval
函数结合 mutate
:
ID_all <- left_join(ID_list, Attendance, by = ID)
ID_all <- mutate(ID_all, Y1_att = ifelse(**column name** %within% interval(DOB, Y1), **value from column name**, NA)
其中星号中的值取自 Attendance
数据框。然后的想法是遍历取自 Attendance
数据框的列,但我不确定如何在计算中使用它的同时在 mutate
函数中引用列,或者是否有更好的方法这样做的方法比从一开始就加入两个数据帧。
您可以在此处执行多种操作来解决您的问题。
首先,ID_list
并不是很有用,因为生日通常恰好以一年分隔,因此您可以自动检索该值。其次,出勤数据集的格式不适合您想要实现的目标:它很宽(列的数量可能会密集增加)并且更容易处理。
为此,您可以使用包 tidyr
中的新函数 pivot_longer
和 pivot_wider
(之前名为 gather
和 spread
) .
library(lubridate)
library(tidyverse)
ID_list = read.table(text = "
ID DOB Y1 Y2 Y3
1 01/05/2003 01/05/2004 01/05/2005 01/05/2006
2 05/02/2010 05/02/2011 05/02/2012 05/02/2013
3 17/06/2015 17/06/2016 17/06/2017 17/06/2018
", header=T)
Attendance = read.table(text = "
ID 01/07/2010 01/07/2011 01/07/2012
4 100% 50% 75%
2 60% 40% 30%
6 80% 60% 100%
", header=T)
Attendance_long = Attendance %>%
pivot_longer(-ID, names_to = "date", values_to = "percent") %>%
mutate(date=date %>% str_remove("X") %>% str_replace_all("\.", "/") %>% as.Date("%d/%m/%Y")) #dates as columns behave badly, needs refactoring :-(
Attendance_long
# A tibble: 9 x 3
# ID date percent
# <int> <date> <fct>
#1 4 2010-07-01 100%
#2 4 2011-07-01 50%
#3 4 2012-07-01 75%
#4 2 2010-07-01 60%
#5 2 2011-07-01 40%
#6 2 2012-07-01 30%
#7 6 2010-07-01 80%
#8 6 2011-07-01 60%
#9 6 2012-07-01 100%
有了长格式的出勤率,您现在可以加入数据并计算出勤日期和出生日期(上限)之间的差值年数。然后,为了达到您的预期输出,您可以再次转向宽格式并删除不必要的列。
ID_all = ID_list %>% as_tibble %>%
select(ID, DOB) %>% #don't need other columns
left_join(Attendance_long, by="ID") %>%
mutate_at(vars(DOB), as.Date, format="%d/%m/%Y") %>%
mutate(year = ceiling(interval(DOB, date) / years(1)),
year = ifelse(!is.na(year), paste0("Y", year, "_att"), year))%>%
select(-date) %>% #important to pivot
pivot_wider(names_from = year,
values_from = percent) %>%
select(-`NA`, -DOB)
ID_all
希望对您有所帮助!
我有两个数据帧 ID_list
和 Attendance
:
ID_list
包含唯一 ID 的列表、他们的出生日期和他们生命中随后几年的生日
ID DOB Y1 Y2 Y3
1 01/05/2003 01/05/2004 01/05/2005 01/05/2006
2 05/02/2010 05/02/2011 05/02/2012 05/02/2013
3 17/06/2015 17/06/2016 17/06/2017 17/06/2018
Attendance
包含一个 ID 列表,其中一些与 ID_list
中的 ID 和不同日期的出席率数字相匹配:
ID 01/07/2010 01/07/2011 01/07/2012
4 100% 50% 75%
2 60% 40% 30%
6 80% 60% 100%
我想生成一个新的数据框,其中包含 ID 列表及其生命中每一年的出勤率,其中 Attendance
数据框中列标题中指定的日期介于两个之间ID_List
数据框中的日期。基于上面的示例,它看起来像这样:
ID Y1_att Y2_att Y3_att
1 NA NA NA
2 60% 40% 30%
3 NA NA NA
我一直在尝试使用 %within%
和 interval
函数结合 mutate
:
ID_all <- left_join(ID_list, Attendance, by = ID)
ID_all <- mutate(ID_all, Y1_att = ifelse(**column name** %within% interval(DOB, Y1), **value from column name**, NA)
其中星号中的值取自 Attendance
数据框。然后的想法是遍历取自 Attendance
数据框的列,但我不确定如何在计算中使用它的同时在 mutate
函数中引用列,或者是否有更好的方法这样做的方法比从一开始就加入两个数据帧。
您可以在此处执行多种操作来解决您的问题。
首先,ID_list
并不是很有用,因为生日通常恰好以一年分隔,因此您可以自动检索该值。其次,出勤数据集的格式不适合您想要实现的目标:它很宽(列的数量可能会密集增加)并且更容易处理。
为此,您可以使用包 tidyr
中的新函数 pivot_longer
和 pivot_wider
(之前名为 gather
和 spread
) .
library(lubridate)
library(tidyverse)
ID_list = read.table(text = "
ID DOB Y1 Y2 Y3
1 01/05/2003 01/05/2004 01/05/2005 01/05/2006
2 05/02/2010 05/02/2011 05/02/2012 05/02/2013
3 17/06/2015 17/06/2016 17/06/2017 17/06/2018
", header=T)
Attendance = read.table(text = "
ID 01/07/2010 01/07/2011 01/07/2012
4 100% 50% 75%
2 60% 40% 30%
6 80% 60% 100%
", header=T)
Attendance_long = Attendance %>%
pivot_longer(-ID, names_to = "date", values_to = "percent") %>%
mutate(date=date %>% str_remove("X") %>% str_replace_all("\.", "/") %>% as.Date("%d/%m/%Y")) #dates as columns behave badly, needs refactoring :-(
Attendance_long
# A tibble: 9 x 3
# ID date percent
# <int> <date> <fct>
#1 4 2010-07-01 100%
#2 4 2011-07-01 50%
#3 4 2012-07-01 75%
#4 2 2010-07-01 60%
#5 2 2011-07-01 40%
#6 2 2012-07-01 30%
#7 6 2010-07-01 80%
#8 6 2011-07-01 60%
#9 6 2012-07-01 100%
有了长格式的出勤率,您现在可以加入数据并计算出勤日期和出生日期(上限)之间的差值年数。然后,为了达到您的预期输出,您可以再次转向宽格式并删除不必要的列。
ID_all = ID_list %>% as_tibble %>%
select(ID, DOB) %>% #don't need other columns
left_join(Attendance_long, by="ID") %>%
mutate_at(vars(DOB), as.Date, format="%d/%m/%Y") %>%
mutate(year = ceiling(interval(DOB, date) / years(1)),
year = ifelse(!is.na(year), paste0("Y", year, "_att"), year))%>%
select(-date) %>% #important to pivot
pivot_wider(names_from = year,
values_from = percent) %>%
select(-`NA`, -DOB)
ID_all
希望对您有所帮助!