Google 工作表分箱和分组依据自定义时间间隔

问题描述

我希望计算在自定义时间间隔内发生的事件:可能是 24 小时内,也可能是一周或 2 个月的跨度。

我正在使用谷歌表格:我可以创建一个数据透视表并按月分组,但是我想使用自定义间隔来探索见解(我正在寻找癫痫症的模式)。

作为最终结果,我想要一个表格,每天报告该间隔内的频率数。

特别是,我想关注 24 小时的间隔来计算癫痫(称为丛集性癫痫发作)事件的数量

然后,按照自定义的天数间隔来探索周期性或趋势 - 例如每 48 小时,或者每 15 或 30 天。

在此处查看 Google Sheet 的模型:

https://docs.google.com/spreadsheets/d/1tCxYV5mUcq6vKm8-fL-0HUAOjcB9fipLCqPD2Znv-X0/edit#gid=1372548551


我尝试过这种尝试:

  1. 了解在报告日期之前的过去 30 天内发生了多少事件:
= IFERROR(
  QUERY(                                                
     A:E,"SELECT COUNT(A)                                   
      WHERE 
        A IS NOT NULL AND 
        E = FALSE AND 
        A >= date '" & 
          TEXT(
            A2-30,"yyyy-MM-dd"                                
          ) &"' AND
        A <= date '" & 
          TEXT(
            A2,"yyyy-MM-dd"                                
          ) &"'

    LABEL COUNT(A) '' "),"N/A")

然后,拖动单元格,我会看到“过去 30 天内的# 个事件”列。

它有效,但似乎有点混乱 - 特别是更新间隔。

  1. 我尝试了另一种方法
=query(B:E,"select B,count(E),-1+count(E) where E = FALSE group by B label B 'Date with Clusters',count(E) 'Cluster seizures '")

这会产生最后一个表。

我更喜欢这种方法,但在这里我只是按同一日期分组,不可能有自定义间隔。

例如,我将在同一天计算两个事件,而不是相同的 24 小时间隔。

您能否说出一种更好的方法来处理日期时间差异,以便使用自定义间隔创建分箱和分组?

下面是一个例子: 在左表中,输入数据;在中间列,第一种方法的结果;在右表中,第二种方法的结果。

enter image description here

解决方法

给定表格:

为了使用 QUERY 对内容进行分组,我们需要“修复”A 列以获得自定义句点。假设我们需要每 3 周(21 天)对事件进行分组。我们取最低和最高日期并创建一个序列,其中包含所有介于两者之间的日期。

=INDEX(ROW(INDIRECT(MIN(A2:A)&":"&MAX(A2:A))))

然后我们对其使用运行总计来获取与上一个/下一个相隔 21 天的每个日期。我们可以使用简单的 SEQUENCE(对于 min>max)来创建这个数组,但是使用 SEQUENCE 我们不能“回到过去”(对于 max>min)所以我们使用 MMULT 和负数

因此,要从第一个日期的框架开始并按窗口创建 3 周组(例如 min>max),我们使用:

=ARRAYFORMULA({MIN(A2:A); MIN(A2:A)+MMULT(TRANSPOSE((
 ROW(INDIRECT(MIN(A2:A)&":"&MAX(A2:A)))<=TRANSPOSE(
 ROW(INDIRECT(MIN(A2:A)&":"&MAX(A2:A)))))*21); SiGN(
 ROW(INDIRECT(MIN(A2:A)&":"&MAX(A2:A)))))})

并反转它并从结束日期的框架开始并向后创建 3 周窗口(例如 max>min),我们使用:

=ARRAYFORMULA({MAX(A2:A); MAX(A2:A)+MMULT(TRANSPOSE((
 ROW(INDIRECT(MIN(A2:A)&":"&MAX(A2:A)))<=TRANSPOSE(
 ROW(INDIRECT(MIN(A2:A)&":"&MAX(A2:A)))))*-21); SiGN(
 ROW(INDIRECT(MIN(A2:A)&":"&MAX(A2:A)))))})

enter image description here

在这个阶段,我们可以通过 VLOOKUP 和第 4 个参数设置为 1 - 近似模式(而不是 0 - 精确匹配模式)开始修复 A 列,因此向前的时间将是:

=ARRAYFORMULA(IFNA(VLOOKUP(A2:A; SORT({MIN(A2:A); MIN(A2:A)+MMULT(TRANSPOSE((
 ROW(INDIRECT(MIN(A2:A)&":"&MAX(A2:A)))<=TRANSPOSE(
 ROW(INDIRECT(MIN(A2:A)&":"&MAX(A2:A)))))*21); SIGN(
 ROW(INDIRECT(MIN(A2:A)&":"&MAX(A2:A)))))}); 1; 1)))

时间倒退应为:

=ARRAYFORMULA(IFNA(VLOOKUP(A2:A; SORT({MAX(A2:A); MAX(A2:A)+MMULT(TRANSPOSE((
 ROW(INDIRECT(MIN(A2:A)&":"&MAX(A2:A)))<=TRANSPOSE(
 ROW(INDIRECT(MIN(A2:A)&":"&MAX(A2:A)))))*-21); SIGN(
 ROW(INDIRECT(MIN(A2:A)&":"&MAX(A2:A)))))}); 1; 1)))

enter image description here

现在我们只需创建一个虚拟数组 {} 并将固定列 A 与列 C 配对并将其作为范围输入到 QUERY

附注:

我们使用 ,

在英文电子表格中将列彼此相邻放置

为了在非英文电子表格中将列彼此相邻放置,我们使用 \

=ARRAYFORMULA(QUERY({IFNA(VLOOKUP(A2:A; SORT({MIN(A2:A); MIN(A2:A)+MMULT(TRANSPOSE((
 ROW(INDIRECT(MIN(A2:A)&":"&MAX(A2:A)))<=TRANSPOSE(
 ROW(INDIRECT(MIN(A2:A)&":"&MAX(A2:A)))))*21); SIGN(
 ROW(INDIRECT(MIN(A2:A)&":"&MAX(A2:A)))))}); 1; 1))\ C2:C}; 
 "select Col1,count(Col1) 
  where Col2 = FALSE 
  group by Col1 
  order by count(Col1) desc 
  label count(Col1)''"))

时间倒退:

=ARRAYFORMULA(QUERY({IFNA(VLOOKUP(A2:A; SORT({MAX(A2:A); MAX(A2:A)+MMULT(TRANSPOSE((
 ROW(INDIRECT(MIN(A2:A)&":"&MAX(A2:A)))<=TRANSPOSE(
 ROW(INDIRECT(MIN(A2:A)&":"&MAX(A2:A)))))*-21); SIGN(
 ROW(INDIRECT(MIN(A2:A)&":"&MAX(A2:A)))))}); 1; 1))\ C2:C}; 
 "select Col1,count(Col1) 
  where Col2 = FALSE 
  group by Col1 
  order by count(Col1) desc 
  label count(Col1)''"))

enter image description here

demo spreadsheet