Chapter 8 - Parsing Unix timestamps

8.1 Parsing Unix timestamps

It’s not obvious how to deal with Unix timestamps in pandas – it took me quite a while to figure this out. The file we’re using here is a popularity-contest file I found on my system at /var/log/popularity-contest.

Here’s an explanation of how this file works.

I’m going to hope that nothing in it is sensitive :)

import pandas as pd
# Read it, and remove the last row
popcon = pd.read_csv('popularity-contest', sep=' ', )[:-1]
popcon.columns = ['atime', 'ctime', 'package-name', 'mru-program', 'tag']
popcon[:5]

The colums are the access time, created time, package name, recently used program, and a tag

Output:

atimectimepackage-namemru-programtag
013872957971367633260perl-base/usr/bin/perlNaN
113872957961354370480login/bin/suNaN
213872957431354341275libtalloc2/usr/lib/x86_64-linux-gnu/libtalloc.so.2.0.7NaN
313872957431387224204libwbclient0/usr/lib/x86_64-linux-gnu/libwbclient.so.0<RECENT-CTIME>
413872957421354341253libselinux1/lib/x86_64-linux-gnu/libselinux.so.1NaN

The magical part about parsing timestamps in pandas is that numpy datetimes are already stored as Unix timestamps. So all we need to do is tell pandas that these integers are actually datetimes – it doesn’t need to do any conversion at all.

We need to convert these to ints to start:

popcon['atime'] = popcon['atime'].astype(int)
popcon['ctime'] = popcon['ctime'].astype(int)

Every numpy array and pandas series has a dtype – this is usually int64, float64, or object. Some of the time types available are datetime64[s], datetime64[ms], and datetime64[us]. There are also timedelta types, similarly.

We can use the pd.to_datetime function to convert our integer timestamps into datetimes. This is a constant-time operation – we’re not actually changing any of the data, just how pandas thinks about it.

popcon['atime'] = pd.to_datetime(popcon['atime'], unit='s')
popcon['ctime'] = pd.to_datetime(popcon['ctime'], unit='s')
popcon['atime'].dtype

Output:

dtype('<M8[ns]')

If we look at the dtype now, it’s <M8[ns]. As far as I can tell M8 is secret code for datetime64.

So now we can look at our atime and ctime as dates!

popcon[:5]

Output:

atimectimepackage-namemru-programtag
02013-12-17 15:56:372013-05-04 02:07:40perl-base/usr/bin/perlNaN
12013-12-17 15:56:362012-12-01 14:01:20login/bin/suNaN
22013-12-17 15:55:432012-12-01 05:54:35libtalloc2/usr/lib/x86_64-linux-gnu/libtalloc.so.2.0.7NaN
32013-12-17 15:55:432013-12-16 20:03:24libwbclient0/usr/lib/x86_64-linux-gnu/libwbclient.so.0<RECENT-CTIME>
42013-12-17 15:55:422012-12-01 05:54:13libselinux1/lib/x86_64-linux-gnu/libselinux.so.1NaN

Now suppose we want to look at all packages that aren’t libraries.

First, I want to get rid of everything with timestamp 0. Notice how we can just use a string in this comparison, even though it’s actually a timestamp on the inside? That is because pandas is amazing.

popcon = popcon[popcon['atime'] > '1970-01-01']

Now we can use pandas’ magical string abilities to just look at rows where the package name doesn’t contain ‘lib’.

nonlibraries = popcon[~popcon['package-name'].str.contains('lib')]
nonlibraries.sort('ctime', ascending=False)[:10]

Output:

atimectimepackage-namemru-programtag
572013-12-17 04:55:392013-12-17 04:55:42ddd/usr/bin/ddd<RECENT-CTIME>
4502013-12-16 20:03:202013-12-16 20:05:13nodejs/usr/bin/npm<RECENT-CTIME>
4542013-12-16 20:03:202013-12-16 20:05:04switchboard-plug-keyboard/usr/lib/plugs/pantheon/keyboard/options.txt<RECENT-CTIME>
4452013-12-16 20:03:202013-12-16 20:05:04thunderbird-locale-en/usr/lib/thunderbird-addons/extensions/langpac...<RECENT-CTIME>
3962013-12-16 20:08:272013-12-16 20:05:03software-center/usr/sbin/update-software-center<RECENT-CTIME>
4492013-12-16 20:03:202013-12-16 20:05:00samba-common-bin/usr/bin/net.samba3<RECENT-CTIME>
3972013-12-16 20:08:252013-12-16 20:04:59postgresql-client-9.1/usr/lib/postgresql/9.1/bin/psql<RECENT-CTIME>
3982013-12-16 20:08:232013-12-16 20:04:58postgresql-9.1/usr/lib/postgresql/9.1/bin/postmaster<RECENT-CTIME>
4522013-12-16 20:03:202013-12-16 20:04:55php5-dev/usr/include/php5/main/snprintf.h<RECENT-CTIME>
4402013-12-16 20:03:202013-12-16 20:04:54php-pear/usr/share/php/XML/Util.php<RECENT-CTIME>

Okay, cool, it says that I I installed ddd recently. And postgresql! I remember installing those things. Neat.

The whole message here is that if you have a timestamp in seconds or milliseconds or nanoseconds, then you can just “cast” it to a datetime64[the-right-thing] and pandas/numpy will take care of the rest.

Where from here?

This was an attempt to provide concise cookbook with real life examples. We suggest you to have a look at the official cookbook also.

Help us improve this content by editing this page on GitHub