【问题标题】:Python, CSV: count number of male employees for each 30 min segmentPython,CSV:计算每 30 分钟段的男性员工人数
【发布时间】:2018-07-06 12:22:58
【问题描述】:

给出的内容:

  • 办公室由 3 种类型的建筑物组成:A 楼、B 楼、C 楼。
  • 员工在 3 个部门工作:IT、营销、管理
  • 有一个通行证系统,记录时间、部门、建筑类型、性别(男/女)

目标是计算每 30 分钟片段中每个部门建筑类型对的男性员工数量。

这是要处理的一段 CSV 数据:

time,department,building_type,gender
2017-09-07 14:46:14,018,management,b,m
2017-09-07 14:49:14,081,it,a,m
2017-09-07 14:55:14,127,management,c,f
2017-09-07 15:40:16,318,marketing,c,m
2017-09-07 16:01:14,018,it,a,m
2017-09-07 16:10:14,081,it,a,m
2017-09-07 17:46:14,127,marketing,c,m
2017-09-07 17:49:16,318,management,c,m
2017-09-07 18:00:14,018,it,c,f
2017-09-07 18:02:14,081,management,a,m
2017-09-07 18:33:14,127,marketing,b,m
2017-09-07 18:56:16,318,marketing,a,m
  • 处理的主要时间段是 2017-09-07 14:46:14,018 到 2017-09-07 18:56:16,318。

  • 应在此主要时间段内定义 30 分钟段,并应每 30 分钟段计算每个部门建筑类型对的男性雇员人数。

  • 输出应包含一列 start_time,表示应计算每个部门建筑对的男性员工数量的 30 分钟段的开始。

  • 输出应显示在终端(不需要csv格式)

输出示例:

start_time,department,building_type,num_of_m_employees
2017-09-07 14:46:14,018,management,b,2
2017-09-07 14:46:14,018,it,a,1
2017-09-07 15:40:16,318,marketing,c,1
2017-09-07 15:40:16,318,it,a,2
2017-09-07 17:46:14,127,marketing,c,1
2017-09-07 17:46:14,127,management,a,1
2017-09-07 18:33:14,127,marketing,b,1
2017-09-07 18:33:14,127,marketing,a,1

我编写了一个程序,该程序通常计算每个部门建设对的男性员工人数,但我不能对每个 30 分钟的部分都做同样的事情。我该如何编辑它?:

import csv
from collections import Counter

with open('test.csv') as f:
    cnt = Counter()
    reader = csv.reader(f)
    for row in reader:
        if row[3] == "m":
            cnt[row[2], row[3]] += 1

print(cnt)

【问题讨论】:

  • 感谢您在问题细节和格式方面所做的努力,但下次请展示您在 30 分钟片段上的尝试
  • 我还建议阅读有关如何正确使用 Counter 的文档。

标签: python csv datetime


【解决方案1】:

希望这能让你开始:

import csv
from collections import Counter
from datetime import datetime, timedelta

with open('test.csv') as f_input:
    csv_input = csv.reader(f_input)
    header = next(csv_input)
    start_time = None
    thirty_mins = timedelta(minutes=30)
    cnt = Counter()

    for row in csv_input:
        # Convert the first entry into a datetime object 
        dt = datetime.strptime("{} {:06}".format(row[0], int(row[1]) * 1000), '%Y-%m-%d %H:%M:%S %f')

        if start_time == None:
            start_time = dt

        if dt >= start_time + thirty_mins:
            for (dept, type), count in cnt.items():
                print('{} {:03},{},{},{}'.format(start_time.strftime('%Y-%m-%d %H:%M:%S'), start_time.microsecond//1000, dept, type, count))
            start_time += thirty_mins
            cnt = Counter()

        if row[4] == "m":
            cnt[row[2], row[3]] += 1

for (dept, type), count in cnt.items():
    print('{} {:03},{},{},{}'.format(start_time.strftime('%Y-%m-%d %H:%M:%S'), start_time.microsecond//1000, dept, type, count))

想法是将时间转换为datetime 对象。有了它,您可以确定一行是否在接下来的 30 分钟范围内。您的第二列似乎包含毫秒。日期时间格式使用微秒,因此需要转换和添加。

读取每一行并转换时间。接下来确定我们是否已经通过了 30 分钟的边界。如果是这样,则显示该边界的计数器值并重置计数器。将时间边界提前 30 分钟。否则,如果该行是男性,则添加到计数器。

最后,打印最后一个边界的所有剩余条目。

对于你给出的例子,这会给你:

2017-09-07 14:46:14 018,management,b,1
2017-09-07 14:46:14 018,it,a,1
2017-09-07 15:16:14 018,marketing,c,1
2017-09-07 15:46:14 018,it,a,2
2017-09-07 16:16:14 018,marketing,c,1
2017-09-07 16:46:14 018,management,c,1
2017-09-07 17:46:14 018,management,a,1
2017-09-07 18:16:14 018,marketing,b,1
2017-09-07 18:46:14 018,marketing,a,1

注意,有些边界不包含条目。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-14
    • 2013-02-28
    相关资源
    最近更新 更多