如何用R语言dplyr包一次性计算人员在各国的时间占比?
用dplyr实现人员跨国停留时间占比统计
数据集
myt = structure(list(name = c("Alice", "Bob", "Bob", "Charlie", "Diana", "Diana", "Eve", "Eve", "Frank", "Frank", "Frank", "Grace", "Grace", "Henry", "Henry", "Henry"), country = c("USA", "Canada", "Mexico", "UK", "France", "Germany", "USA", "Canada", "Mexico", "USA", "UK", "France", "Germany", "USA", "Canada", "Mexico"), date_arrived = structure(c(17897, 18414, 18536, 18779, 18231, 18475, 18597, 18687, 18048, 18322, 18567, 17897, 18762, 18383, 18489, 18597), class = "Date"), date_left = structure(c(18322, 18506, 18659, 18840, 18444, 18567, 18659, 2932896, 18231, 18506, 2932896, 18353, 18809, 18489, 18597, 18748), class = "Date")), class = "data.frame", row.names = c(NA, -16L))
统计需求
- 针对2020年5月1日至2021年5月1日期间有数据的所有人员;
- 计算该时间段内他们在每个国家的停留时间占比;
- 若人员覆盖整个时间段,分母用365天;否则用其实际停留总天数(即取365和实际总天数的较小值);
- 同一日期人员仅可能在一个国家,但可在年内往返多国。
dplyr一站式实现代码
library(dplyr) # 定义时间段 period_start <- as.Date("2020-05-01") period_end <- as.Date("2021-05-01") total_period_days <- as.numeric(period_end - period_start) final_results <- myt %>% # 计算有效停留起止日期(截断到目标时间段内) mutate( effective_arrival = pmax(date_arrived, period_start), effective_departure = pmin(date_left, period_end), # 判断是否在时间段内有停留,计算有效停留天数 in_range = effective_arrival < effective_departure, num_days_in_range = ifelse(in_range, as.numeric(effective_departure - effective_arrival), 0) ) %>% # 筛选出在时间段内有停留的记录 filter(in_range) %>% # 按姓名+国家聚合,计算每个国家的停留天数 group_by(name, country) %>% summarise(days_in_country = sum(num_days_in_range), .groups = "drop_last") %>% # 按姓名聚合,计算个人总停留天数,同时确定分母 mutate( total_days_present = sum(days_in_country), denominator = pmin(total_days_present, total_period_days) ) %>% # 计算占比并保留两位小数 mutate(percentage = round(100 * days_in_country / denominator, 2)) %>% # 按姓名和国家排序,整理列顺序 arrange(name, country) %>% select(name, country, days_in_country, total_days_present, denominator, percentage) # 查看结果 print(final_results)
代码说明
mutate阶段:对应基础R中计算有效日期、判断是否在范围内、计算停留天数的步骤,直接在原数据上新增列,无需拆分数据框;filter阶段:筛选出有有效停留的记录,替代基础R中myt_in_range的子集操作;- 链式聚合操作:先用
group_by(name, country)计算每个国家的停留天数,再通过.groups = "drop_last"保留姓名分组,直接计算个人总停留天数和分母,避免了基础R中两次aggregate再merge的繁琐; - 排序和列整理:用
arrange和select一步完成排序和列顺序调整,代码更直观。
内容的提问来源于stack exchange,提问作者stats_noob
相关产品推荐
相关产品推荐

