r语言 - 高效地将"individual clock in/out time logs"转换为"total occupancy of building over time"



所以我有.csv形式的数据,显示了特定用户在几个月内进出建筑物的时间。我正在尝试使用 R 每 15/30 分钟将建筑物占用率制成表格进行分析。

数据已被清理,采用大型ffdf数据框(~1100 万个条目)的形式。数据框具有numericfactor类型(它包括以后可能有用的字符串和数字),并且上班打卡/下班时间位于格式为 POSIXct 的列中。

如果这是一个小得多的数据集,我会执行以下操作:

  • 创建一个空.csv文件(即occupancy)来存储占用级别,时间作为列标题,日期作为行。
  • 使用 for 循环跨所有行迭代以下内容:
    • 计算建筑总时间(下班打卡 - 打卡时间)
    • 从打卡条目中提取日期,存储为inDate
    • 使用plyr包中的round_any查找最接近的 15 分钟开始时间上限,存储为nearest15
    • 通过floor(as.numeric((clockouttime - clockintime)/15))查找用户占用的完整 15 分钟街区数量
    • 1 添加到用户正在构建的相关时间段数,从 occupancy[inDate, nearest15] 开始。

但是,遍历 1100 万行的 for 循环根本效率不高。

有谁知道如何有效地做到这一点?我不知所措 - 据我所知,apply系列函数会将所有数据强制为单一类型。如果您不熟悉它们,则不需要特定的命令,我只是希望有人指出正确的软件包和实现的一般想法。

我目前正在使用ff来访问数据,但如果有更好的软件包可以做到这一点,我愿意接受建议。

谢谢。

编辑:

这是我正在查看的代码的编辑片段:

user_hash, section_hash, dept_id, col_a, col_b, clockin_datetime, clockout_datetime EEDD1DA7F38CA42A35CF3C003B,85C7,TS,1,,2013-08-08 12:52:00,2013-08-08 23:00:00 2BCB6AA1603BB4357BC0D390C9,BFA3,VS,1,,2013-08-08 12:48:00,2013-08-08 22:58:00 46D859B55C4802DF51445025C5,943B,TS,1,,2013-08-08 11:58:00,2013-08-08 16:04:00 FE4EEA83AF6EA50CA5738B5610,00B3,VT,1,,2013-08-08 19:56:00,2013-08-08 23:04:00 8DB43D322F0AEF6D2B877862C3,DB1F,TS,1,,2013-08-08 12:49:00,2013-08-08 13:03:00 4E636571D425A74CA6B5FA7909,1860,VS,1,,2013-08-08 12:21:00,2013-08-08 14:01:00 26B41FA581408BDFD747234640,FDA4,VS,1,,2013-08-08 20:38:00,2013-08-08 23:03:00 A6C3C190BFFDCB4194774C1026,45C0,VT,1,,2013-08-08 12:58:00,2013-08-08 20:03:00 938506D977353EA65DC6BB5260,1819,VT,1,,2013-08-08 12:54:00,2013-08-08 16:01:00 E82F9350DA9FFC73EE6A66A286,04C1,VT,1,,2013-08-08 08:42:00,2013-08-08 12:45:00 6B92F1AB6B3EE193430B6B2793,6C2E,TS,1,,2013-08-08 09:58:00,2013-08-08 13:03:00 2B88836D8A4CA5183AAE5D3D9A,497C,TS,2,,2013-08-08 10:35:00,2013-08-08 16:06:00

我想到的所需输出是这样的,尽管任何显示我在任何给定时间段/日期的占用情况的形式都可以。

date 12.00 12.15 12.30 12.45 ....... 2013-08-01 1344 1632 3742 1024 2013-08-02 342 435 435 435 2013-08-03 2013-08-04 ...

我过去曾使用过类似的数据,发现重新排列数据会有所帮助。首先,我假设您的日期已正确编码为日期值,并且您的示例数据位于名为 dd 的 data.frame 中。例如

dd <- structure(list(user_hash = structure(c(11L, 3L, 4L, 12L, 7L, 
5L, 1L, 9L, 8L, 10L, 6L, 2L), .Label = c("26B41FA581408BDFD747234640", 
"2B88836D8A4CA5183AAE5D3D9A", "2BCB6AA1603BB4357BC0D390C9", "46D859B55C4802DF51445025C5", 
"4E636571D425A74CA6B5FA7909", "6B92F1AB6B3EE193430B6B2793", "8DB43D322F0AEF6D2B877862C3", 
"938506D977353EA65DC6BB5260", "A6C3C190BFFDCB4194774C1026", "E82F9350DA9FFC73EE6A66A286", 
"EEDD1DA7F38CA42A35CF3C003B", "FE4EEA83AF6EA50CA5738B5610"), class = "factor"), 
    section_hash = structure(c(8L, 10L, 9L, 1L, 11L, 4L, 12L, 
    5L, 3L, 2L, 7L, 6L), .Label = c("00B3", "04C1", "1819", "1860", 
    "45C0", "497C", "6C2E", "85C7", "943B", "BFA3", "DB1F", "FDA4"
    ), class = "factor"), dept_id = structure(c(1L, 2L, 1L, 3L, 
    1L, 2L, 2L, 3L, 3L, 3L, 1L, 1L), .Label = c("TS", "VS", "VT"
    ), class = "factor"), col_a = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L, 1L, 2L), col_b = c(NA, NA, NA, NA, NA, NA, NA, 
    NA, NA, NA, NA, NA), clockin_datetime = structure(c(1375980720, 
    1375980480, 1375977480, 1376006160, 1375980540, 1375978860, 
    1376008680, 1375981080, 1375980840, 1375965720, 1375970280, 
    1375972500), class = c("POSIXct", "POSIXt"), tzone = ""), 
    clockout_datetime = structure(c(1376017200, 1376017080, 1375992240, 
    1376017440, 1375981380, 1375984860, 1376017380, 1376006580, 
    1375992060, 1375980300, 1375981380, 1375992360), class = c("POSIXct", 
    "POSIXt"), tzone = "")), .Names = c("user_hash", "section_hash", 
"dept_id", "col_a", "col_b", "clockin_datetime", "clockout_datetime"
), row.names = c(NA, -12L), class = "data.frame")

现在,如果您将数据安排为具有输入/退出时间流,并为进入建筑物的人员分配+1的值,在他们离开建筑物时分配-1的值,则会产生类似

dx <- rbind(
   data.frame(val=1, time=dd$clockin_datetime), 
   data.frame(val=-1, time=dd$clockout_datetime)
)
dx <- dx[order(dx$time), ]

然后,要查找任何给定时间的人数,您只需要在 val 列上做一个累积总和

transform(dx, pop=cumsum(val))

然后,您可以将其拆分为间隔。

对于规模的数据,使用 data.tables 而不是 data.frame 在性能方面可能更好,但调整内容以找出最适合您的数据的内容将需要更大的测试用例。但我认为这种总体策略可能非常有用。

相关内容

最新更新