如何计算每天一个标志状态的经过时间?

数据挖掘 时间序列 大数据
2022-02-27 17:09:52

我想弄清楚标志状态更改之间经过的时间。

简化示例:一个人只能悲伤或快乐。我想知道每种情绪在改变之前活跃了多长时间。

我正在使用通用存储和脚本来循环记录,这非常昂贵。我正在寻找一般的最佳实践我愿意结合使用任何技术或作为替代技术。我是数据科学的新手,可能会错过正确的术语。非常感谢相关建议。

索引:user_mood_log

 |    changed_at    |  mood  | user |
 ------------------------------
 | yyyy-mm-dd 12:00 | sad    | John |
 | yyyy-mm-dd 15:00 | happy  | John |
 | yyyy-mm-dd 18:00 | happy  | John |
 |        ...       |   ...  |  ... |

索引:user_mood_log_daily

 |    date    |  sad  | happy | user |
 -------------------------------------
 | 2019-05-22 |   3   |   21  | John |
 | 2019-05-21 |   5   |   19  | John |
 |    ...     |  ...  |   ... |  ... |

挑战:

  1. 需要考虑昨天(甚至更早)的最后一条记录。意味着我不能简单地按天分组。
  2. 情绪可能几天都不会改变。
  3. 重复的情绪日志是可能的。

有什么建议吗?提前致谢!

2个回答

Python 的pandas包能够回答所有这些问题,前提是数据可以放入计算机的内存中。

Pandas 可以处理时间序列数据、查找时间增量和删除重复项

您可以将Wolfram 语言应用到您的项目中。有一个免费的Wolfram 引擎供开发人员使用,可插入许多 IDE。它还有用于 Python 的Wolfram 客户端库以在 Python中使用这些函数。

我认为有一个 API 可以将数据作为 JSON 或 CSV 或这些或其他格式的流获取。根据 API,您可以使用HTTP 请求和响应指南或Web 操作指南中的函数。

由于没有提供数据,我将从生成定时情绪运行开始。为了确保有运行,我将使用DiscreteMarkovProcess带有转换矩阵的 a ,该矩阵略微偏向于当前状态而不是移动到另一个状态。

MatrixForm[tm = {{0.6, 0.4}, {0.4, 0.6}}]

数学图形

Graph可以采用 aDiscreteMarkovProcess所以可以将其可视化为

mood = DiscreteMarkovProcess[1, tm];
Graph@mood

数学图形

或为清晰起见进行一些格式化。

Graph[
 Flatten@MapIndexed[Labeled[DirectedEdge @@ #2, #1] &, tm, {2}],
 VertexSize -> Medium,
 VertexStyle -> LightGreen,
 VertexLabels -> Thread[Range[2] -> Map[Placed[#, Center] &, {"Happy", "Sad"}]]
 ]

数学图形

RandomFunction将模拟这个过程,我会将整数值转换为文本,ReplaceAll (/.)以便具有与 ElasticSearch 中相同的数据类型。DateRange将用于创建相隔 2 小时的时间戳,如您的示例所示。

SeedRandom[987]
n = 20;
data = Transpose@
   {
    With[{start = DateObject@{2019, 1, 1, 0}},
     DateRange[start, DatePlus[start, {2 n, "Hour"}], Quantity[2, "Hour"]]
     ],
    RandomFunction[mood, {0, n}]["Values"] /. Thread[Range@2 -> {"Happy", "Sad"}]
    };

这给出了下面的快乐-悲伤序列,如下所示DateListPlot

DateListPlot[KeySort@GroupBy[Last]@data /. Thread[{"Happy", "Sad"} -> Range@2],
 Joined -> False]

数学图形

现在有了数据,就可以开始实际工作了。前 2 项是

data[[;; 2]]

数学图形

data可以是每个项目中SplitByLast值。这些运行可以是Transposed ,因此有一行DateObjects 和一个字符串值。Apply (@@@)输入MinMax日期和First值(因为它们对于每次运行都是相同的)获取每次运行的起点和终点。

runs = {MinMax@#1, First@#2} & @@@ Transpose /@ SplitBy[data, Last]

数学图形

我已决定在之前的运行结束后立即开始运行,并在其最后一个数据点结束。因此,我需要包含上一次运行的终点来计算运行的运行时间。通过Fold成对的列表 ( FoldPairList)可以计算前一个结尾和当前结尾之间的中间值DateDifference"Hour"

runTimes =
 FoldPairList[
  {
    {DateDifference[##, "Hour"] & @@ MinMax@Rest@Flatten@{##}[[All, 1]], Last@#2},
    #2
   } &,
  First@runs,
  runs
 ]

数学图形

DateDifference返回Quantity请求的时间单位的对象。

runTimes[[1, 1]] // InputForm
Quantity[8, "Hours"]

数量对象在整个语言中都是已知的,因此可以从这里继续进行进一步的处理或分析。例如像这样的BarChart可视化

BarChart[Labeled @@@ runTimes, ChartLabels -> Automatic, AxesLabel -> Automatic]

数学图形

请注意,小时的缩写被Automatic放置为AxesLabel.

希望这可以帮助。