Querying the graph over time

Raphtory allows you to create windows that cover a specified time period and generate views from a window, this is sometimes called filtering. You can then get a final result by applying a function to the view object. This means you can run algorithms against a subset of your data and track the evolution of variables across time.

All of the time view functions can be called on a Graph, Node, or Edge, returning an equivalent GraphView, NodeView or EdgeView which have all the same functions as its unfiltered counterpart. This means that if you write a function which takes a Raphtory entity, it will work regardless of which filters have been applied.

Creating views At, After and Before a specified time

The simplest of these functions, before(), at() and after() take a singular time argument in epoch (integer) or datetime (string or datetime object) format and return a view of the object which includes:

  • at() - Only updates which happened at exactly the time specified.
  • after() - All updates between the specified time and the end of the graph's history, exclusive of the time specified.
  • before() - All updates between the beginning of the graph's history and the specified time, exclusive of the time specified.
  • latest() - A convenience function equivalent to g.at(g.latest_time), returning only the most recent state of the graph.

While before() and after() are more useful for continuous time datasets, at() can be helpful when you have snapshots or logical timestamps and want to look at them individually to compare and contrast. The latest() function is particularly useful when you want to query the current state without needing to know the exact timestamp.

In the example below we print the degree of Lome across the full dataset, before 12:17 on the 13th of June, after 9:07 on the 30th of June, at the earliest time, and at the latest time. We also use two time functions here, start and end, which return information about a view.

Notice in the output that the start and end show None for unbounded times - when using before() we don't need a start bound (we include everything up until the specified point), and when using after() we don't need an end bound (we include everything from the specified point onwards).

Window

The window() function allows you create a view that is restricted by both a start time as well as an end time, inclusive of the start and exclusive of the end time. This is useful for examining specific ranges of your graph's history.

In the example below, we look at the number of times Lome interacts with Nekke within the full dataset and for one day between the 13th of June and the 14th of June. We use datetime objects in this example, but it would work the same with string dates and epoch integers.

Shrinking windows

Raphtory provides three functions for narrowing an existing window:

These functions always stay within the bounds of the original window. If you attempt to shrink to a time outside of the original window, the value is clamped to the original bounds (effectively ignored):

Window Sets

When analysing temporal graphs, you often want to examine how metrics evolve over time. Rather than manually creating individual windows, Raphtory provides two powerful functions that generate sequences of views automatically: expanding() for cumulative analysis and rolling() for sliding window analysis.

Both functions support natural language time intervals like "1 week", "2 days, 3 hours", or "1 month", making it easy to express complex temporal queries in a readable way.

Expanding

Use expanding() to iterate over multiple time points with cumulative windows. Each view includes all history from the start up to that point, growing larger with each step.

Using expanding() will return an iterable of views as if you called before() from the earliest time to the latest time at increments of a given step. The start of each window is aligned with the smallest unit of time passed by the user within the step. Alternatively, you can explicitly specify an alignment_unit that determines when the window starts.

The step can be specified using a simple epoch integer, or a natural language string describing the interval. For the latter, the string is converted into an iterator of datetimes, handling all corner cases like varying month length and leap years.

Within the string you can reference years, months weeks, days, hours, minutes, seconds and milliseconds. These can be singular or plural and the string can include and, spaces, and commas to improve readability.

The example below demonstrates two cases. In the first case, we increment through the full history of the graph a week at a time. This creates four views, for each of which we ask how many monkey interactions it has seen. You will notice the start time does not change, but the end time increments by 7 days each view.

The second case shows the complexity of increments Raphtory can handle, stepping by 2 days, 3 hours, 12 minutes and 6 seconds each time. We have additionally bounded this iterable using a window between the 13th and 23rd of June to demonstrate how these views may be chained.

Rolling

You can use rolling() to create a rolling window instead of including all prior history. This function will return an iterable of views, incrementing by a window size and only including the history from inside the window period, inclusive of start, exclusive of end. This allows you to easily extract daily or monthly metrics.

Alongside the window size, rolling() takes an optional step argument which specifies how far along the timeline it should increment before applying the next window. By default this is the same as window, allowing all updates to be analyzed exactly once in non-overlapping windows. If you want overlapping or fully disconnected windows, you can set a step smaller or greater than the given window size. Optionally you can also specify an alignment_unit to determine where the window should begin (e.g., aligned to the start of a month or week).

For example, you can take the code from expanding and swap out the function for rolling(). In the loop you can see both the start date and end date increase by seven days each time, and the number of monkey interactions sometimes decreases as older data is dropped from the window.

Snapshots

When writing functions that may receive either a Graph or a PersistentGraph, you may want consistent behaviour regardless of the graph type. Raphtory provides two snapshot functions that give you known semantics across both:

  • snapshot_at(time) — Returns a view including all events that have not been explicitly deleted at the given time. This is equivalent to before(time + 1) for a regular Graph, and at(time) for a PersistentGraph.

  • snapshot_latest() — Returns a view including all events that have not been explicitly deleted at the latest time. This is a no-op for a regular Graph, and equivalent to latest() for a PersistentGraph.

These functions are useful when you need to query the "current state" of a graph without knowing what type it is. For more details on the difference between Graph and PersistentGraph, see the Time Semantics section.