【问题标题】:Using R, how can I count objects according to multiple conditions?使用 R,如何根据多个条件计算对象?
【发布时间】:2020-04-15 05:40:49
【问题描述】:

我正在尝试根据某些条件对 911 呼叫的数据帧中的对象进行计数,但我遇到了逻辑问题。我的实际数据有超过 300 万行,所以我试图通过考虑这个小子集来简化我的问题:

dat <- structure(list(call = c("14-1234", "14-4523", "14-7711", "14-8199", "14-3124"), 
                      badge = c("8456", "1098", "3432", "4750", "5122"),
                      off.sex = c("Male", "Male", "Female", "Male", "Male"),
                      shift = c("1", "1", "1", "1", "2"),
                      assignedmin = c(1902, 1870, 1950, 1899, 1907),
                      clearedmin = c(1980, 1910, 1990, 1912, 1956)),
                 class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -5L))

变量“call”标识 911 呼叫,“badge”标识官员,“shift”基本上标识特定区域的一段时间。来电的具体分钟由“assignedmin”给出,并且在“clearedmin”给出的时间认为呼叫已清除。

我想计算给定班次中有多少官员能够响应特定呼叫。例如,对于呼叫 14-1234,在时间 1902 分配了 8456 警官。有多少其他警官能够响应该电话?从 1870 分钟到 1910 分钟,警官 1098 忙于处理不同的呼叫,因此无法响应在 1902 分钟发生的呼叫。但是,基于这个简单的数据集,警官 3432 当时不会很忙因此将被视为可用。 5122 警官当时无人值守,但在不同的班次,因此不被视为有空。

期望的输出:

  call    badge off.sex shift assignedmin clearedmin n_shift n_avail n_unavail n_shift_male n_male_avail
1 14-1234 8456  Male    1            1902       1980       4       2         2            3            1
2 14-4523 1098  Male    1            1870       1910       4       4         0            3            3
3 14-7711 3432  Female  1            1950       1990       4       3         1            3            2
4 14-8199 4750  Male    1            1899       1912       4       3         1            3            2
5 14-3124 5122  Male    2            1907       1956       1       1         1            1            1

我希望这不会太复杂。基本上,在assignmin 给定的时间,如果他或她在同一个班次并且没有忙于另一个电话,则他或她有空。我可以使用 dplyr 和 data.table 轻松计算轮班人员的数量,如下所示:

dat <- dat %>% group_by(shift) %>% mutate(n_shift = uniqueN(badge),
                                          n_shift_male = uniqueN(badge[off.sex == 'Male']) %>% ungroup()

【问题讨论】:

    标签: r dplyr data.table


    【解决方案1】:

    使用data.table 计算每个班次的人员数量的选​​项,然后执行非等自连接以找出n_unavail,最后是n_avail = n_shift - n_unavail

    library(data.table)
    setDT(dat)[, c("n_shift", "n_shift_male") := .(.N, sum(off.sex=="Male")), shift]
    
    dat[, c("n_unavail", "n_male_not_avail") :=
            dat[dat, on=.(shift, assignedmin<=assignedmin, clearedmin>=assignedmin),
                by=.EACHI, .(.N - 1L, sum(x.off.sex[x.call != i.call]=="Male"))][,
                    (1L:3L) := NULL]
        ]
    
    dat[, c("n_avail", "n_male_avail") := .(n_shift - n_unavail, n_shift_male - n_male_not_avail)]
    

    输出:

          call badge off.sex shift assignedmin clearedmin n_shift n_shift_male n_unavail n_male_not_avail n_avail n_male_avail
    1: 14-1234  8456    Male     1        1902       1980       4            3         2                2       2            1
    2: 14-4523  1098    Male     1        1870       1910       4            3         0                0       4            3
    3: 14-7711  3432  Female     1        1950       1990       4            3         1                1       3            2
    4: 14-8199  4750    Male     1        1899       1912       4            3         1                1       3            2
    5: 14-3124  5122    Male     2        1907       1956       1            1         0                0       1            1
    

    【讨论】:

    • 感谢您的帮助。有没有办法修改它,以便我也可以通过 off.sex 计算可用人员的数量?我对 data.table 相当陌生。
    • 您可以将所需的 n_shift_male 输出添加到您的帖子中吗?谢谢!
    • 我已将 n_shift_male 和 n_male_avail 所需的输出添加到帖子中。再次感谢。
    • @hunter,我添加了一些代码来计算这个要求。你可能想检查一下。
    • 谢谢,这适用于我给出的示例,它也适用于我的完整数据的更大样本。如果我可以问最后一个问题,你能想出为什么这不适用于我的超过 300 万个观测值的完整数据集的原因吗?我收到此错误: vecseq 中的错误(f__, len__, if (allow.cartesian || notjoin || !anyDuplicated(f__, :
    【解决方案2】:

    n_unavail 列可以填写如下。首先,我在shift 上单独加入表格,以便同一班次中的每个军官组合都有一行(如果您的数据集很大,这可能是不可行的)。然后,我计算_other官员在通话时是否不可用,并统计。

    dat %>% 
      left_join(dat, by = "shift", suffix = c("", "_other")) %>% 
      mutate(unavail = (assignedmin_other < assignedmin & clearedmin_other > assignedmin)) %>% 
      group_by(call) %>% 
      summarise(n_avail = sum(!unavail),
                n_unavail = sum(unavail))
    
    #   call    n_avail n_unavail
    #   <chr>     <int>     <int>
    # 1 14-1234       2         2
    # 2 14-3124       1         0
    # 3 14-4523       4         0
    # 4 14-7711       3         1
    # 5 14-8199       3         1
    

    这可以加入到您的表中以获得您想要的结果。

    【讨论】:

      猜你喜欢
      • 2022-01-15
      • 2019-02-06
      • 1970-01-01
      • 2012-12-14
      • 2021-07-14
      • 2019-07-04
      • 2021-08-24
      • 1970-01-01
      • 2018-12-07
      相关资源
      最近更新 更多