Periodic pattern mining, an example with Canadian TV programs

logo

[1]:
import skmine

print("This tutorial was tested with the following version of skmine :", skmine.__version__)

print("""
Be sure to execute this notebook in the dir `docs/tutorials/periodic`,
to be able to load the data files `.csv`.
If not, please do so and adapt the bash commands below
""")

%pwd
# %cd docs/tutorials/periodic
This tutorial was tested with the following version of skmine : 1.0.0

Be sure to execute this notebook in the dir `docs/tutorials/periodic`,
to be able to load the data files `.csv`.
If not, please do so and adapt the bash commands below

[1]:
'/home/hcourtei/Projects/F-WIN/scikit-mine/codes/skMineDev/docs/tutorials/periodic'

The problem, informally

Let’s take a simple example.

Imagine you set an alarm to wake up every day around 7:30AM, and go to work. Sometimes you wake up a bit earlier (your body anticipates the alarm), and sometimes a bit later, for example if you press the “snooze” button and refuse to face the fact that you have to wake up.

In python we can load those “wake up” events as logs, and store them in a pandas.Series, like

[2]:
import datetime as dt
import pandas as pd

one_day = 60 * 24  # a day in minutes
minutes = [0, one_day - 1, one_day * 2 - 1, one_day * 3, one_day * 4 + 2, one_day * 7]

S = pd.Series("wake up", index=minutes)
start = dt.datetime.strptime("16/04/2020 07:30", "%d/%m/%Y %H:%M")
S.index = S.index.map(lambda e: start + dt.timedelta(minutes=e))
S.index = S.index.round("min")  # minutes as the lowest unit of difference
S
[2]:
2020-04-16 07:30:00    wake up
2020-04-17 07:29:00    wake up
2020-04-18 07:29:00    wake up
2020-04-19 07:30:00    wake up
2020-04-20 07:32:00    wake up
2020-04-23 07:30:00    wake up
dtype: object
[3]:
S.index.to_numpy()
[3]:
array(['2020-04-16T07:30:00.000000000', '2020-04-17T07:29:00.000000000',
       '2020-04-18T07:29:00.000000000', '2020-04-19T07:30:00.000000000',
       '2020-04-20T07:32:00.000000000', '2020-04-23T07:30:00.000000000'],
      dtype='datetime64[ns]')

We can see the wake-up time is not exactly the same every day, but overall a consistent regular pattern seems to emerge.

Now imagine that in addition to wake up times, we also have records of other daily activities (meals, work, household chores, etc.), and that rather than a handful of days, those records span several years and make up several thousands of events

Can you automatically identify regularities to better understand your daily routine?

Introduction to periodic pattern mining

Periodic pattern mining aims at exploiting regularities not only about what happens by finding coordinated event occurrences, but also about when it happens and how it happens. It’s about not just finding things that happen repeatedly, but that happen regularly, with a consistent periodicity.

Next, we introduce the concept of cycles

The cycle : a building block for periodic pattern mining

Here is an explicit example of a cycle

cycle

This definition, while being relatively simple, is general enough to allow us to find regularities in different types of logs

Handling noise in our timestamps

Needless to say, it would be too easy if events in our data were equally spaced. As data often comes noisy, we have to be fault tolerant, and allow small errors to sneak into our cycles.

That’s the role of **shift corrections*, which capture the small deviations from perfectly regular periodic repetitions, and allow to reconstruct the (noisy) original sequence of events, using the following relation shifts

A tiny example with scikit-mine

scikit-mine offers a PeriodicPatternMiner, out of the box. You can use it to detect regularities, in the form of (possibly nested) cycles, which we call periodic patterns.

These patterns are evaluated using a MDL criterion, to help us extract a compact and representative collection of patterns from the data, trying to avoid redundancy between patterns, in particular.

[4]:
from skmine.periodic import PeriodicPatternMiner
pcm = PeriodicPatternMiner().fit(S)
pcm.transform(S)
[4]:
t0 pattern repetition_major period_major sum_E
0 2020-04-16 07:30:00 (wake up)[r=5 p=1 day, 0:00:00] 5 1 days 0 days 00:04:00

You can see one cycle has been extracted for our event wake up. The cycle covers the entire business week, but not the last monday separated by the weekend

It has a length of 5 and a period close to 1 day, as expected.

Also, note that we mix some information here. Our period of 1 day offers the best summary for this data. Accessing the little “shifts” as encountered in original data is also possible, with an extra argument in our call : pcm.transform(S,dE_sum=False)

[5]:
pd.set_option('display.max_colwidth', 100)
res_wake = pcm.transform(S,dE_sum=False)
res_wake.E

[5]:
0    [-1 days +23:59:00, 0 days 00:00:00, 0 days 00:01:00, 0 days 00:02:00]
Name: E, dtype: object

The last column named E contains a list of shifts to apply to our cycle in case we want to reconstruct the original data. Trailing zeros have been removed for efficiency, and their values are relative to the period, but we can see there is: * -1 minute shift (-1 days +23:59:00), between the 1st and 2nd entry (waking up at 7:30 on 04-16 at 7:29 on 04-17) * no shift between the 2nd and 3rd entry (still waking up at 7:29 on 04-18) * + 1 minute shift between the 3rd and 4th entry (back to 7:30 on 04-19) * + 2 minutes shift between the 4th and 5th entry (waking up at 7:32 on 04-20)

Events that are not captured by any pattern are called redisuals

[6]:
pcm.get_residuals()
[6]:
time event
0 2020-04-23 07:30:00 wake up

This way pcm does not store all the data, but has all information needed to reconstruct it entirely !!

[7]:
pcm.reconstruct()
[7]:
time event
0 2020-04-16 07:30:00 wake up
1 2020-04-17 07:29:00 wake up
2 2020-04-18 07:29:00 wake up
3 2020-04-19 07:30:00 wake up
4 2020-04-20 07:32:00 wake up

An example with Canadian TV programs

Fetching logs from canadian TV

In this section we are going to load some event logs of TV programs (the WHAT), indexed by their broadcast timestamps (the WHEN).

PeriodicPatternMiner is here to help us discovering regularities (the HOW)

[8]:
from skmine.datasets import fetch_canadian_tv
from skmine.periodic import PeriodicPatternMiner

Searching for cycles in TV programs

Remember about the definition of cycles ? Let’s apply it to our TV programs

In our case

  • \(\alpha\) is the name of a TV program

  • \(r\) is the number of broadcasts (repetitions) for this TV program (inside this cycle)

  • \(p\) is the optimal time delta between broadcasts in this cycle. If a program is meant to be live everyday at 14:00PM, then \(p\) is likely to be 1 day

  • \(\tau\) is the first broadcast time in this cycle

  • \(dE\) are the shift corrections between the \(p\) and the actual broadcast time of an event. If a TV program was scheduled at 8:30:00AM and it went on air at 8:30:23AM the same day, then we keep track of a 23 seconds shift. This way we can summarize our data (via cycles), and reconstruct it (via shift corrections).

Finally we are going to dig a little deeper into these cycles, to answer quite complex questions about our logs. We will see that cycles contains usefull information about our input data

[9]:
ctv_logs = fetch_canadian_tv()
ctv_logs.head()
[9]:
timestamp
2020-08-01 06:00:00            The Moblees
2020-08-01 06:11:00    Big Block Sing Song
2020-08-01 06:13:00    Big Block Sing Song
2020-08-01 06:15:00               CBC Kids
2020-08-01 06:15:00               CBC Kids
Name: canadian_tv, dtype: string

Compute only simple cycles on ctv_logs with the karg complex=False :

[10]:
pcm = PeriodicPatternMiner(complex=False).fit(ctv_logs)
pcm.transform(ctv_logs)
/home/hcourtei/Projects/F-WIN/scikit-mine/codes/skMineDev/skmine/periodic/cycles.py:131: UserWarning: found 234 duplicates in the input sequence, they have been removed.
  warnings.warn(f"found {diff} duplicates in the input sequence, they have been removed.")
[10]:
t0 pattern repetition_major period_major sum_E
20 2020-08-01 04:00:00 (Rick Mercer Report)[r=5 p=7 days, 0:00:00] 5 7 days 00:00:00 0 days 00:00:00
21 2020-08-01 04:30:00 (Rick Mercer Report)[r=5 p=7 days, 0:00:00] 5 7 days 00:00:00 0 days 00:00:00
0 2020-08-01 05:00:00 (Grand Designs)[r=31 p=1 day, 0:00:00] 31 1 days 00:00:00 0 days 00:00:00
59 2020-08-01 06:00:00 (The Moblees)[r=5 p=7 days, 0:00:00] 5 7 days 00:00:00 0 days 00:00:00
29 2020-08-01 06:11:00 (Big Block Sing Song)[r=5 p=7 days, 0:00:00] 5 7 days 00:00:00 0 days 00:00:00
... ... ... ... ... ...
254 2020-08-26 14:00:00 (Jamie's Super Foods)[r=3 p=1 day, 0:00:00] 3 1 days 00:00:00 0 days 00:00:00
183 2020-08-27 02:00:00 (Mr. D)[r=4 p=0:30:00] 4 0 days 00:30:00 0 days 00:00:00
2 2020-08-28 00:00:00 (Schitt's Creek)[r=8 p=0:30:00] 8 0 days 00:30:00 0 days 00:00:00
129 2020-08-29 06:15:00 (CBC Kids)[r=23 p=0:12:00] 23 0 days 00:12:00 0 days 02:26:00
126 2020-08-30 06:11:00 (CBC Kids)[r=11 p=0:12:00] 11 0 days 00:12:00 0 days 00:49:00

278 rows × 5 columns

Compute simple and complex (with horizontal and vertical combinations) cycles on ctv_logs :

[11]:
pcm = PeriodicPatternMiner(complex=True).fit(ctv_logs)
/home/hcourtei/Projects/F-WIN/scikit-mine/codes/skMineDev/skmine/periodic/cycles.py:131: UserWarning: found 234 duplicates in the input sequence, they have been removed.
  warnings.warn(f"found {diff} duplicates in the input sequence, they have been removed.")
[12]:
pd.set_option('display.max_colwidth', 100)
cycles = pcm.transform(ctv_logs)
cycles
[12]:
t0 pattern repetition_major period_major sum_E
34 2020-08-01 04:00:00 (Rick Mercer Report [d=0:30:00] Rick Mercer Report)[r=5 p=7 days, 0:00:00] 5 7 days 00:00:00 0 days 00:00:00
0 2020-08-01 05:00:00 (Grand Designs)[r=31 p=1 day, 0:00:00] 31 1 days 00:00:00 0 days 00:00:00
7 2020-08-01 06:00:00 (The Moblees [d=0:11:00] Big Block Sing Song [d=0:02:00] Big Block Sing Song [d=0:02:00] CBC Kid... 5 7 days 00:00:00 0 days 00:03:00
19 2020-08-01 06:15:00 (CBC Kids [d=1:40:00] Big Block Sing Song [d=0:02:00] Furchester Hotel [d=0:38:00] Ollie: The Bo... 5 7 days 00:00:00 0 days 00:02:00
95 2020-08-01 06:15:00 (CBC Kids)[r=29 p=0:12:00] 29 0 days 00:12:00 0 days 02:54:00
... ... ... ... ... ...
109 2020-08-26 14:00:00 (Jamie's Super Foods)[r=3 p=1 day, 0:00:00] 3 1 days 00:00:00 0 days 00:00:00
86 2020-08-27 02:00:00 (Mr. D)[r=4 p=0:30:00] 4 0 days 00:30:00 0 days 00:00:00
16 2020-08-28 00:00:00 (Schitt's Creek)[r=8 p=0:30:00] 8 0 days 00:30:00 0 days 00:00:00
100 2020-08-29 06:15:00 (CBC Kids)[r=23 p=0:12:00] 23 0 days 00:12:00 0 days 02:26:00
92 2020-08-31 07:00:00 (CBC Kids)[r=17 p=0:13:00] 17 0 days 00:13:00 0 days 02:15:00

121 rows × 5 columns

Note : no need to worry for the warning, it’s here to notify duplicate event/timestamp pairs have been found

Viewing the patterns

Sometimes the patterns are complicated to understand textually. The draw_pattern function allows you to visualise them. Simply indicate in pattern the id of the pattern you wish to view from the results of the previous transform.

[13]:
pcm.draw_pattern(19)
# if you want to save the tree, you can add a `directory` parameter to indicate the location of the results (pdf + generated DOT file)
[13]:
../../_images/tutorials_periodic_periodic_pattern_mining_on_canadian_TV_logs_27_0.svg

Patterns import - export

[14]:
#Store in a json file the patterns ("patterns.json" by default)
pcm.export_patterns(file = "patterns.json")

# reinitialize the PeriodicPatternMiner :
pcm = PeriodicPatternMiner()

# import the json file ("patterns.json" by default)
pcm.import_patterns(file = "patterns.json")

# recompute the pattern :
cycles = pcm.transform(ctv_logs)
cycles
[14]:
t0 pattern repetition_major period_major sum_E
0 2020-08-01 04:00:00 (Rick Mercer Report [d=0:30:00] Rick Mercer Report)[r=5 p=7 days, 0:00:00] 5 7 days 00:00:00 0 days 00:00:00
1 2020-08-01 05:00:00 (Grand Designs)[r=31 p=1 day, 0:00:00] 31 1 days 00:00:00 0 days 00:00:00
2 2020-08-01 06:00:00 (The Moblees [d=0:11:00] Big Block Sing Song [d=0:02:00] Big Block Sing Song [d=0:02:00] CBC Kid... 5 7 days 00:00:00 0 days 00:03:00
3 2020-08-01 06:15:00 (CBC Kids [d=1:40:00] Big Block Sing Song [d=0:02:00] Furchester Hotel [d=0:38:00] Ollie: The Bo... 5 7 days 00:00:00 0 days 00:02:00
4 2020-08-01 06:15:00 (CBC Kids)[r=29 p=0:12:00] 29 0 days 00:12:00 0 days 02:54:00
... ... ... ... ... ...
116 2020-08-26 14:00:00 (Jamie's Super Foods)[r=3 p=1 day, 0:00:00] 3 1 days 00:00:00 0 days 00:00:00
117 2020-08-27 02:00:00 (Mr. D)[r=4 p=0:30:00] 4 0 days 00:30:00 0 days 00:00:00
118 2020-08-28 00:00:00 (Schitt's Creek)[r=8 p=0:30:00] 8 0 days 00:30:00 0 days 00:00:00
119 2020-08-29 06:15:00 (CBC Kids)[r=23 p=0:12:00] 23 0 days 00:12:00 0 days 02:26:00
120 2020-08-31 07:00:00 (CBC Kids)[r=17 p=0:13:00] 17 0 days 00:13:00 0 days 02:15:00

121 rows × 5 columns

Now that we have our cycles in a pandas.DataFrame, we can play with the pandas API and answer questions about our logs

Did I find cycles for the TV show “Arthurt Shorts”

[15]:
cycles
[15]:
t0 pattern repetition_major period_major sum_E
0 2020-08-01 04:00:00 (Rick Mercer Report [d=0:30:00] Rick Mercer Report)[r=5 p=7 days, 0:00:00] 5 7 days 00:00:00 0 days 00:00:00
1 2020-08-01 05:00:00 (Grand Designs)[r=31 p=1 day, 0:00:00] 31 1 days 00:00:00 0 days 00:00:00
2 2020-08-01 06:00:00 (The Moblees [d=0:11:00] Big Block Sing Song [d=0:02:00] Big Block Sing Song [d=0:02:00] CBC Kid... 5 7 days 00:00:00 0 days 00:03:00
3 2020-08-01 06:15:00 (CBC Kids [d=1:40:00] Big Block Sing Song [d=0:02:00] Furchester Hotel [d=0:38:00] Ollie: The Bo... 5 7 days 00:00:00 0 days 00:02:00
4 2020-08-01 06:15:00 (CBC Kids)[r=29 p=0:12:00] 29 0 days 00:12:00 0 days 02:54:00
... ... ... ... ... ...
116 2020-08-26 14:00:00 (Jamie's Super Foods)[r=3 p=1 day, 0:00:00] 3 1 days 00:00:00 0 days 00:00:00
117 2020-08-27 02:00:00 (Mr. D)[r=4 p=0:30:00] 4 0 days 00:30:00 0 days 00:00:00
118 2020-08-28 00:00:00 (Schitt's Creek)[r=8 p=0:30:00] 8 0 days 00:30:00 0 days 00:00:00
119 2020-08-29 06:15:00 (CBC Kids)[r=23 p=0:12:00] 23 0 days 00:12:00 0 days 02:26:00
120 2020-08-31 07:00:00 (CBC Kids)[r=17 p=0:13:00] 17 0 days 00:13:00 0 days 02:15:00

121 rows × 5 columns

[16]:
cycles[cycles["pattern"].apply(lambda x: "Arthur Shorts" in x)]
[16]:
t0 pattern repetition_major period_major sum_E
15 2020-08-01 10:48:00 (Addison [d=0:12:00] Arthur Shorts [d=0:13:00] Stella & Sam [d=0:12:00] Wandering Wenda [d=0:34:... 5 7 days 00:00:00 0 days 00:00:00
50 2020-08-03 09:35:00 ((Arthur Shorts [d=0:13:00] Arthur Shorts)[r=5 p=1 day, 0:00:00] [d=0:45:00] (Furchester Hotel [... 3 6 days 23:59:00 0 days 00:22:00
112 2020-08-24 09:35:00 (Arthur Shorts [d=0:13:00] Arthur Shorts [d=0:15:00] Kiri & Lou [d=0:17:00] Furchester Hotel [d=... 5 0 days 23:59:00 0 days 00:11:00

What are the top 10 longest cycles ?

[17]:
cycles.nlargest(10, ["repetition_major"])
[17]:
t0 pattern repetition_major period_major sum_E
1 2020-08-01 05:00:00 (Grand Designs)[r=31 p=1 day, 0:00:00] 31 1 days 00:00:00 0 days 00:00:00
6 2020-08-01 06:57:00 (CBC Kids)[r=31 p=1 day, 0:00:00] 31 1 days 00:00:00 0 days 00:33:00
4 2020-08-01 06:15:00 (CBC Kids)[r=29 p=0:12:00] 29 0 days 00:12:00 0 days 02:54:00
105 2020-08-22 06:15:00 (CBC Kids)[r=27 p=0:12:00] 27 0 days 00:12:00 0 days 02:14:00
95 2020-08-15 06:15:00 (CBC Kids)[r=25 p=0:12:00] 25 0 days 00:12:00 0 days 02:00:00
73 2020-08-08 06:15:00 (CBC Kids)[r=23 p=0:11:00] 23 0 days 00:11:00 0 days 02:42:00
119 2020-08-29 06:15:00 (CBC Kids)[r=23 p=0:12:00] 23 0 days 00:12:00 0 days 02:26:00
120 2020-08-31 07:00:00 (CBC Kids)[r=17 p=0:13:00] 17 0 days 00:13:00 0 days 02:15:00
106 2020-08-23 06:11:00 (CBC Kids)[r=12 p=0:13:00] 12 0 days 00:13:00 0 days 00:38:00
68 2020-08-07 00:13:00 (Schitt's Creek)[r=8 p=0:30:00] 8 0 days 00:30:00 0 days 00:13:00
[18]:
pcm.reconstruct([1])
[18]:
time event
0 2020-08-01 05:00:00 Grand Designs
1 2020-08-02 05:00:00 Grand Designs
2 2020-08-03 05:00:00 Grand Designs
3 2020-08-04 05:00:00 Grand Designs
4 2020-08-05 05:00:00 Grand Designs
5 2020-08-06 05:00:00 Grand Designs
6 2020-08-07 05:00:00 Grand Designs
7 2020-08-08 05:00:00 Grand Designs
8 2020-08-09 05:00:00 Grand Designs
9 2020-08-10 05:00:00 Grand Designs
10 2020-08-11 05:00:00 Grand Designs
11 2020-08-12 05:00:00 Grand Designs
12 2020-08-13 05:00:00 Grand Designs
13 2020-08-14 05:00:00 Grand Designs
14 2020-08-15 05:00:00 Grand Designs
15 2020-08-16 05:00:00 Grand Designs
16 2020-08-17 05:00:00 Grand Designs
17 2020-08-18 05:00:00 Grand Designs
18 2020-08-19 05:00:00 Grand Designs
19 2020-08-20 05:00:00 Grand Designs
20 2020-08-21 05:00:00 Grand Designs
21 2020-08-22 05:00:00 Grand Designs
22 2020-08-23 05:00:00 Grand Designs
23 2020-08-24 05:00:00 Grand Designs
24 2020-08-25 05:00:00 Grand Designs
25 2020-08-26 05:00:00 Grand Designs
26 2020-08-27 05:00:00 Grand Designs
27 2020-08-28 05:00:00 Grand Designs
28 2020-08-29 05:00:00 Grand Designs
29 2020-08-30 05:00:00 Grand Designs
30 2020-08-31 05:00:00 Grand Designs
[19]:
pcm.get_residuals()
[19]:
time event
143 2020-08-01 01:12:00 OLYMPIC GAMES REPLAY
287 2020-08-01 13:00:00 Bondi Vet
47 2020-08-01 13:30:00 Basketball
122 2020-08-01 15:55:00 Basketball
347 2020-08-01 19:00:00 Still Standing
... ... ...
351 2020-08-31 16:00:00 Escape to the Country
348 2020-08-31 17:00:00 Murdoch Mysteries
409 2020-08-31 17:59:00 News
386 2020-08-31 19:00:00 Hockey Night in Canada
74 2020-08-31 23:15:00 CBC News: The National

454 rows × 2 columns

what are the 10 most unpunctual TV programs ?

For this we are going to : 1. extract the shift corrections along with other informations about our cycles 2. compute the sum of the absolute values for the shift corrections, for every cycles 3. get the 10 biggest sums

[20]:
# full_cycles = pcm.transform(x)
# full_cycles.head()
[21]:
# def absolute_sum(*args):
#     return sum(map(abs, *args))

# # level 0 is the name of the TV program
# shift_sums = full_cycles["dE"].map(absolute_sum).groupby(level=[0]).sum()
# shift_sums.nlargest(10)
[22]:
# def absolute_sum(*args):
#     return sum(map(abs, *args))

# # level 0 is the name of the TV program
# shift_sums = full_cycles["dE"].map(absolute_sum).groupby(level=[0]).sum()
# shift_sums.nlargest(10)

What TV programs have been broadcasted every day for at least 5 days straight?

Let’s make use of the pandas.DataFrame.query method to express our question in an SQL-like syntax

[23]:
# cycles.query('length_major >= 5 and period_major >= 3600', engine='python')
# # cycles.query('length >= 5 and period == "1 days"', engine='python')

What TV programs are broadcast only on business days ?

From the previous query we see we have a lot of 5-length cycles, with periods of 1 day. An intuition is that these cycles take place on business days. Let’s confirm this by considering cycles with 1. start timestamps on mondays 2. periods of roughly 1 day

[24]:
# monday_starts = cycles[cycles.start.dt.weekday == 0]  # start on monday
# monday_starts.query('length == 5 and period == "1 days"', engine='python')

Load your own custom datasets

If you want to use your own datasets from file, you can use the fetch_file function.
There are 3 ways to write :

1. **Each line consists of a datetime followed by its associated event.

** By default, the separator is a ``,``. This is customisable.
Example :
[25]:
with open("dataset_datetime.csv", "r") as f:
    data = f.read().splitlines()

data
[25]:
['2020-04-16 07:30:00,wake up',
 '2020-04-17 07:29:00,wake up',
 '2020-04-17 07:29:00,wake up',
 '2020-04-18 07:29:00,wake up',
 '2020-04-19 07:30:00,wake up',
 '2020-04-20 07:32:00,wake up',
 '2020-04-23 07:30:00,wake up']
[26]:
from skmine.datasets.periodic import fetch_file

data = fetch_file("dataset_datetime.csv", separator=",")  # by default separator is already comma
pcm = PeriodicPatternMiner().fit(data)
pcm.transform(data)
/home/hcourtei/Projects/F-WIN/scikit-mine/codes/skMineDev/skmine/periodic/cycles.py:131: UserWarning: found 1 duplicates in the input sequence, they have been removed.
  warnings.warn(f"found {diff} duplicates in the input sequence, they have been removed.")
[26]:
t0 pattern repetition_major period_major sum_E
0 2020-04-16 07:30:00 (wake up)[r=5 p=1 day, 0:00:00] 5 1 days 0 days 00:04:00

Note that several formats for datetimes can be infered from example. But you can force to parse string according to a specific format with the extra option : format="%d/%m/%Y %H:%M:%S" . see https://docs.python.org/3/library/datetime.html#strftime-and-strptime-behavior for all possibilities - 2020-04-23 07:30:00 -> YYYY-MM-DD hh:mm:ss - 1997-07-23T19:20+01:00 -> YYYY-MM-DDThh:mmTZD (TZD = time zone designator) - 1997-07-23T19:20:30.45+01:00 -> YYYY-MM-DDThh:mm:ss.sTZD - 02/23/2018 -> MM/DD/YYYY - 02/23/18 -> MM/DD/YY - …

2 points of caution are to be noted: - Beware of this type of format “Feb 23, 2018” (Mth d, YYYY) because comma is the default separator. If you want to use this format, you must use double quotes around the date. - The MM/DD (Month/day) format is infered by default (when day is less than 12), for DD/MM; use format option as in example below:

[27]:
fetch_file("dataset_datetime_DD_MM.csv",  separator=',' ,format="%d/%m/%Y %H:%M:%S")
[27]:
timestamp
2018-02-10 07:30:00    wake up
2018-02-23 07:30:00     coffee
2018-03-10 07:30:00    wake up
Name: dataset_datetime_DD_MM.csv, dtype: string

2. Datetimes can also be replaced by integers.

Example:
[28]:
with open("dataset_integer.csv", "r") as f:
    data = f.read().splitlines()

data
[28]:
['1,wake up',
 '3,wake up',
 '10,wake up',
 '30,wake up',
 '40,wake up',
 '70,wake up',
 '100,wake up']

3. Use only the name of the events.

In this case, the indexes correspond to the line numbers (starting from 0).
Example:
[29]:
with open("dataset_no_index.csv", "r") as f:
    data = f.read().splitlines()

data
[29]:
['wake up', 'wake up', 'wake up', 'wake up', 'wake up', 'wake up', 'wake up']
[30]:
data = fetch_file("dataset_no_index.csv")
data
[30]:
timestamp
0    wake up
1    wake up
2    wake up
3    wake up
4    wake up
5    wake up
6    wake up
Name: dataset_no_index.csv, dtype: string

References

  1. Galbrun, E & Cellier, P & Tatti, N & Termier, A & Crémilleux, B “Mining Periodic Pattern with a MDL Criterion”

  2. Galbrun, E “The Minimum Description Length Principle for Pattern Mining : A survey”

  3. Termier, A “Periodic pattern mining”