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

Python实现无Pandas的按ID分组计算CSV办公时长

不用Pandas按ID分组计算2023年2月办公时长差值

核心思路

不需要嵌套多循环,用字典分组是更高效的方案:

  • 以(用户ID, 日期)作为字典键(比如(101, '2023-02-01')),确保同一人同一天的签到签退时间被归集到同一组
  • 字典值存储该组的签到(in)和签退(out)时间对象,方便后续计算差值

实现步骤

  1. 解析CSV并转换时间格式:将time字段从字符串转为datetime对象,为时长计算做准备
  2. 归集签到签退数据:遍历已筛选的2月数据,填充分组字典
  3. 计算时长并输出结果:遍历分组字典,用签退时间减去签到时间得到当日时长,按需按ID汇总或按日期输出

完整代码示例

假设你的筛选后CSV样例如下:

id,type,time
101,in,2023-02-01 09:00:00
101,out,2023-02-01 18:30:00
102,in,2023-02-01 08:45:00
102,out,2023-02-01 17:15:00
101,in,2023-02-02 09:10:00
101,out,2023-02-02 18:00:00

对应的纯Python实现代码:

import csv
from datetime import datetime

# 初始化分组字典:键=(id, 日期), 值={'in': datetime对象, 'out': datetime对象}
time_records = {}

# 读取筛选后的2月CSV文件(替换为你的实际文件名)
with open('filtered_feb_data.csv', 'r', encoding='utf-8') as f:
    reader = csv.DictReader(f)
    for row in reader:
        user_id = row['id']
        record_type = row['type']
        # 转换时间字符串为datetime对象
        record_time = datetime.strptime(row['time'], '%Y-%m-%d %H:%M:%S')
        # 提取日期字符串作为分组键的一部分
        date_str = record_time.strftime('%Y-%m-%d')
        
        # 初始化该用户当日的记录条目
        key = (user_id, date_str)
        if key not in time_records:
            time_records[key] = {'in': None, 'out': None}
        
        # 填充签到/签退时间
        if record_type == 'in':
            time_records[key]['in'] = record_time
        elif record_type == 'out':
            time_records[key]['out'] = record_time

# 计算时长并整理结果
daily_duration = {}  # 存储每个用户每日的办公时长
total_duration = {}  # 存储每个用户2月总办公时长

for (user_id, date_str), times in time_records.items():
    # 仅当签到和签退时间都存在时计算时长
    if times['in'] and times['out']:
        # 计算当日时长(秒转小时,保留2位小数)
        duration_hours = (times['out'] - times['in']).total_seconds() / 3600
        # 按用户ID和日期存储每日时长
        daily_duration.setdefault(user_id, {})[date_str] = round(duration_hours, 2)
        # 累加用户总时长
        total_duration[user_id] = total_duration.get(user_id, 0) + duration_hours

# 输出每日时长结果
print("每日办公时长:")
for user_id, dates in daily_duration.items():
    print(f"用户ID {user_id}:")
    for date, hours in dates.items():
        print(f"  {date}: {hours}小时")

# 输出2月总时长结果
print("\n2月总办公时长:")
for user_id, total_hours in total_duration.items():
    print(f"用户ID {user_id}: {round(total_hours, 2)}小时")

关键补充

  • 若你还未完成2月数据筛选,可在读取行时添加判断:
    # 仅处理2023年2月的数据
    if record_time.year == 2023 and record_time.month == 2:
        # 执行后续分组逻辑
    
  • 代码包含容错处理:跳过缺失签到或签退时间的记录,避免报错
  • 时间复杂度为O(n),仅需两次线性遍历(一次读数据分组,一次计算时长),比嵌套循环更高效

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 04:55:28