You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在R语言中按用户及场所连续时段分组汇总使用时长?

问题:计算用户连续场所的手机使用总时长

假设记录了随机使用手机的时长数据,需要计算每个用户在连续场所时段的总使用时长(比如Lily有3个连续时段:首次home、随后school、最后home;Sam有2个时段:school、home),无需手动标记period字段,直接从原始数据得到结果。

原始数据的生成代码:

# 生成数据框
library(dplyr)
set.seed(1234)
my_data <- data.frame(
  name = c(rep("Lily", 6), rep("Sam", 4)), 
  log_order = c(1:6, 1:4), 
  place = c(
    rep("home", 2), rep("school", 2), rep("home", 2), 
    rep("school", 2), rep("home", 2)
  ), 
  use_time = sample(1:10, 10)
)

# 查看原始数据
my_data
#>   name log_order  place use_time
#> 1  Lily         1   home       10
#> 2  Lily         2   home        6
#> 3  Lily         3 school        5
#> 4  Lily         4 school        4
#> 5  Lily         5   home        1
#> 6  Lily         6   home        8
#> 7   Sam         1 school        2
#> 8   Sam         2 school        7
#> 9   Sam         3   home        9
#> 10  Sam         4   home        3

期望的最终结果:

#>   name  place tot_use_time
#>   <chr> <chr>        <int>
#> 1 Lily  home            16
#> 2 Lily  school           9
#> 3 Lily  home             9
#> 4 Sam   school           9
#> 5 Sam   home            12

解决方案

通过dplyr的分组和累加逻辑自动生成连续时段的分组标识,无需手动标记period:

my_data %>%
  group_by(name) %>%
  # 自动生成连续时段的分组编号
  mutate(period = cumsum(place != lag(place, default = first(place)))) %>%
  # 按用户、时段、场所汇总时长
  group_by(name, period, place) %>%
  summarise(tot_use_time = sum(use_time), .groups = "drop") %>%
  # 移除period字段
  select(-period)

代码逻辑说明

  1. group_by(name):按用户分组,确保每个用户的时段判断独立
  2. mutate(period = cumsum(place != lag(place, default = first(place)))):
    • lag(place, default = first(place)):获取当前记录的上一条场所值,第一条记录默认用自身的场所值
    • place != lag(...):判断当前场所是否和上一条不同,不同则返回TRUE(即1),相同则返回FALSE(即0)
    • cumsum():累加上述逻辑值,相同的连续场所会被分到同一个period组
  3. 后续的group_by和summarise完成时长汇总,最后移除period字段得到期望结果

内容的提问来源于stack exchange,提问作者Kang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 17:43:19