在 R 中:如何提取有关有效时间段的信息并将其应用于另一个数据集?
In R: How to extract info about valid time periods and apply it to another dataset?
我必须要合并数据集:
数据集 1:包含 "perc" 有效的时间段:
set.seed(1)
example_df <- data.frame(ID = rep(1:2, each=2),
start = c(as.Date("2014-01-01"), as.Date("2014-03-05"), as.Date("2014-01-13"), as.Date("2014-03-15")),
end = c(as.Date("2014-03-05"), as.Date("2014-04-12"), as.Date("2014-03-01"), as.Date("2014-04-02")),
perc = rnorm(mean= 30, sd= 10, 4))
数据集 2:包含每个月的工资:
month_start <- as.Date("2014-01-01") + months(0:3)
month_end <- ceiling_date(month_start, "month") - days(1)
set.seed(1)
example_df2 <- data.frame(month_start, month_end,
ID = rep(1:2, each=4),
pay = rnorm(mean= 2000, sd= 80, 8))
目标是根据每个人工作的 perc 计算每个人每个月的工资。重要的是要考虑 perc 的有效时间段,它可能会在一个月内发生变化。
例如:
ID 1 的 2014 年 1 月:工资 = 1949.884(工资)*23.73546(perc)/100
因为 perc 在整个 1 月份都有效。
但是,对于 3 月,5 日之前的 perc 为 23.73546,3 月剩余时间的 perc 为 31.83643。
因此,
ID 1 的 2014 年 3 月:薪资 = 1949.884(薪资)*23.73546(perc)/100/ 31(三月份的天数)*5 + 1949.884(薪资)*31.83643(perc)/100/ 31(三月份的天数)三月)*26
从 2 个数据帧之间的 left_join()
开始。 ID
的每个工作周期将复制到此 ID
的每个发薪月期间。
然后,我们一连串的ifelse()
,你可以判断是要统计整个月,还是只统计一部分,还是不统计。
library(tidyverse)
result <- example_df %>%
left_join(example_df2, by = 'ID') %>%
mutate(
TEST_MONTH = ifelse(end >= month_start & start < month_end, 1, 0),
TEST_DAYS = ifelse(TEST_MONTH == 1,
ifelse(end > month_end,
ifelse(start >= month_start, month_end - start + 1, month_end - month_start + 1),
end - month_start + 1),
0),
PAID = pay * perc/100 * TEST_DAYS / as.numeric(month_end - month_start + 1)
)
result %>% filter(ID == 1)
# ID start end perc month_start month_end pay TEST_MONTH TEST_DAYS PAID
# 1 1 2014-01-01 2014-03-05 23.73546 2014-01-01 2014-01-31 1949.884 1 31 462.81390
# 2 1 2014-01-01 2014-03-05 23.73546 2014-02-01 2014-02-28 2014.691 1 28 478.19633
# 3 1 2014-01-01 2014-03-05 23.73546 2014-03-01 2014-03-31 1933.150 1 5 74.00678
# 4 1 2014-01-01 2014-03-05 23.73546 2014-04-01 2014-04-30 2127.622 0 0 0.00000
# 5 1 2014-03-05 2014-04-12 31.83643 2014-01-01 2014-01-31 1949.884 0 0 0.00000
# 6 1 2014-03-05 2014-04-12 31.83643 2014-02-01 2014-02-28 2014.691 0 0 0.00000
# 7 1 2014-03-05 2014-04-12 31.83643 2014-03-01 2014-03-31 1933.150 1 27 536.03354
# 8 1 2014-03-05 2014-04-12 31.83643 2014-04-01 2014-04-30 2127.622 1 12 270.94364
我必须要合并数据集:
数据集 1:包含 "perc" 有效的时间段:
set.seed(1)
example_df <- data.frame(ID = rep(1:2, each=2),
start = c(as.Date("2014-01-01"), as.Date("2014-03-05"), as.Date("2014-01-13"), as.Date("2014-03-15")),
end = c(as.Date("2014-03-05"), as.Date("2014-04-12"), as.Date("2014-03-01"), as.Date("2014-04-02")),
perc = rnorm(mean= 30, sd= 10, 4))
数据集 2:包含每个月的工资:
month_start <- as.Date("2014-01-01") + months(0:3)
month_end <- ceiling_date(month_start, "month") - days(1)
set.seed(1)
example_df2 <- data.frame(month_start, month_end,
ID = rep(1:2, each=4),
pay = rnorm(mean= 2000, sd= 80, 8))
目标是根据每个人工作的 perc 计算每个人每个月的工资。重要的是要考虑 perc 的有效时间段,它可能会在一个月内发生变化。
例如:
ID 1 的 2014 年 1 月:工资 = 1949.884(工资)*23.73546(perc)/100
因为 perc 在整个 1 月份都有效。
但是,对于 3 月,5 日之前的 perc 为 23.73546,3 月剩余时间的 perc 为 31.83643。
因此,
ID 1 的 2014 年 3 月:薪资 = 1949.884(薪资)*23.73546(perc)/100/ 31(三月份的天数)*5 + 1949.884(薪资)*31.83643(perc)/100/ 31(三月份的天数)三月)*26
从 2 个数据帧之间的 left_join()
开始。 ID
的每个工作周期将复制到此 ID
的每个发薪月期间。
然后,我们一连串的ifelse()
,你可以判断是要统计整个月,还是只统计一部分,还是不统计。
library(tidyverse)
result <- example_df %>%
left_join(example_df2, by = 'ID') %>%
mutate(
TEST_MONTH = ifelse(end >= month_start & start < month_end, 1, 0),
TEST_DAYS = ifelse(TEST_MONTH == 1,
ifelse(end > month_end,
ifelse(start >= month_start, month_end - start + 1, month_end - month_start + 1),
end - month_start + 1),
0),
PAID = pay * perc/100 * TEST_DAYS / as.numeric(month_end - month_start + 1)
)
result %>% filter(ID == 1)
# ID start end perc month_start month_end pay TEST_MONTH TEST_DAYS PAID
# 1 1 2014-01-01 2014-03-05 23.73546 2014-01-01 2014-01-31 1949.884 1 31 462.81390
# 2 1 2014-01-01 2014-03-05 23.73546 2014-02-01 2014-02-28 2014.691 1 28 478.19633
# 3 1 2014-01-01 2014-03-05 23.73546 2014-03-01 2014-03-31 1933.150 1 5 74.00678
# 4 1 2014-01-01 2014-03-05 23.73546 2014-04-01 2014-04-30 2127.622 0 0 0.00000
# 5 1 2014-03-05 2014-04-12 31.83643 2014-01-01 2014-01-31 1949.884 0 0 0.00000
# 6 1 2014-03-05 2014-04-12 31.83643 2014-02-01 2014-02-28 2014.691 0 0 0.00000
# 7 1 2014-03-05 2014-04-12 31.83643 2014-03-01 2014-03-31 1933.150 1 27 536.03354
# 8 1 2014-03-05 2014-04-12 31.83643 2014-04-01 2014-04-30 2127.622 1 12 270.94364