问题描述
我希望计算在自定义时间间隔内发生的事件:可能是 24 小时内,也可能是一周或 2 个月的跨度。
我正在使用谷歌表格:我可以创建一个数据透视表并按月分组,但是我想使用自定义间隔来探索见解(我正在寻找癫痫症的模式)。
作为最终结果,我想要一个表格,每天报告该间隔内的频率数。
特别是,我想关注 24 小时的间隔来计算癫痫(称为丛集性癫痫发作)事件的数量。
然后,按照自定义的天数间隔来探索周期性或趋势 - 例如每 48 小时,或者每 15 或 30 天。
在此处查看 Google Sheet 的模型:
我尝试过这种尝试:
- 了解在报告日期之前的过去 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 天内的# 个事件”列。
它有效,但似乎有点混乱 - 特别是更新间隔。
- 我尝试了另一种方法:
=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 小时间隔。
您能否说出一种更好的方法来处理日期时间差异,以便使用自定义间隔创建分箱和分组?
下面是一个例子: 在左表中,输入数据;在中间列,第一种方法的结果;在右表中,第二种方法的结果。
解决方法
给定表格:
为了使用 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)))))})
在这个阶段,我们可以通过 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)))
现在我们只需创建一个虚拟数组 {}
并将固定列 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)''"))