Pandas 秘籍 - 第八章
import pandas as pd
8.1 解析 Unix 时间戳
在 pandas 中处理 Unix 时间戳不是很容易 - 我花了相当长的时间来解决这个问题。 我们在这里使用的文件是一个软件包流行度文件,我在我的系统上的/var/log/popularity-contest
找到的。
这里解释了这个文件是什么。
# Read it, and remove the last row
popcon = pd.read_csv('../data/popularity-contest', sep=' ', )[:-1]
popcon.columns = ['atime', 'ctime', 'package-name', 'mru-program', 'tag']
列是访问时间,创建时间,包名称最近使用的程序,以及标签。
popcon[:5]
atime | ctime | package-name | mru-program | tag | |
---|---|---|---|---|---|
0 | 1387295797 | 1367633260 | perl-base | /usr/bin/perl | NaN |
1 | 1387295796 | 1354370480 | login | /bin/su | NaN |
2 | 1387295743 | 1354341275 | libtalloc2 | /usr/lib/x86_64-linux-gnu/libtalloc.so.2.0.7 | NaN |
3 | 1387295743 | 1387224204 | libwbclient0 | /usr/lib/x86_64-linux-gnu/libwbclient.so.0 | |
4 | 1387295742 | 1354341253 | libselinux1 | /lib/x86_64-linux-gnu/libselinux.so.1 | NaN |
pandas 中的时间戳解析的神奇部分是 numpy datetime
已经存储为 Unix 时间戳。 所以我们需要做的是告诉 pandas 这些整数实际上是数据时间 - 它不需要做任何转换。
我们需要首先将这些转换为整数:
popcon['atime'] = popcon['atime'].astype(int)
popcon['ctime'] = popcon['ctime'].astype(int)
每个 numpy 数组和 pandas 序列都有一个dtype
- 这通常是int64
,float64
或object
。 一些可用的时间类型是datetime64
[s],datetime64
[ms]和datetime64
[us]。 与之相似,也有timedelta
类型。
我们可以使用pd.to_datetime
函数将我们的整数时间戳转换为datetimes
。 这是一个常量时间操作 - 我们实际上并不改变任何数据,只是改变了 Pandas 如何看待它。
popcon['atime'] = pd.to_datetime(popcon['atime'], unit='s')
popcon['ctime'] = pd.to_datetime(popcon['ctime'], unit='s')
如果我们现在查看dtype
,它是<M8[ns]
,我们可以分辨出M8
是datetime64
的简写。
popcon['atime'].dtype
dtype('<M8[ns]')
所以现在我们将atime
和ctime
看做时间了。
popcon[:5]
atime | ctime | package-name | mru-program | tag | |
---|---|---|---|---|---|
0 | 2013-12-17 15:56:37 | 2013-05-04 02:07:40 | perl-base | /usr/bin/perl | NaN |
1 | 2013-12-17 15:56:36 | 2012-12-01 14:01:20 | login | /bin/su | NaN |
2 | 2013-12-17 15:55:43 | 2012-12-01 05:54:35 | libtalloc2 | /usr/lib/x86_64-linux-gnu/libtalloc.so.2.0.7 | NaN |
3 | 2013-12-17 15:55:43 | 2013-12-16 20:03:24 | libwbclient0 | /usr/lib/x86_64-linux-gnu/libwbclient.so.0 | |
4 | 2013-12-17 15:55:42 | 2012-12-01 05:54:13 | libselinux1 | /lib/x86_64-linux-gnu/libselinux.so.1 | NaN |
现在假设我们要查看所有不是库的软件包。
首先,我想去掉一切带有时间戳 0 的东西。注意,我们可以在这个比较中使用一个字符串,即使它实际上在里面是一个时间戳。这是因为 Pandas 是非常厉害的。
popcon = popcon[popcon['atime'] > '1970-01-01']
现在我们可以使用 pandas 的魔法字符串功能来查看包名称不包含lib
的行。
nonlibraries = popcon[~popcon['package-name'].str.contains('lib')]
nonlibraries.sort('ctime', ascending=False)[:10]
atime | ctime | package-name | mru-program | tag | |
---|---|---|---|---|---|
57 | 2013-12-17 04:55:39 | 2013-12-17 04:55:42 | ddd | /usr/bin/ddd | |
450 | 2013-12-16 20:03:20 | 2013-12-16 20:05:13 | nodejs | /usr/bin/npm | |
454 | 2013-12-16 20:03:20 | 2013-12-16 20:05:04 | switchboard-plug-keyboard | /usr/lib/plugs/pantheon/keyboard/options.txt | |
445 | 2013-12-16 20:03:20 | 2013-12-16 20:05:04 | thunderbird-locale-en | /usr/lib/thunderbird-addons/extensions/langpac… | |
396 | 2013-12-16 20:08:27 | 2013-12-16 20:05:03 | software-center | /usr/sbin/update-software-center | |
449 | 2013-12-16 20:03:20 | 2013-12-16 20:05:00 | samba-common-bin | /usr/bin/net.samba3 | |
397 | 2013-12-16 20:08:25 | 2013-12-16 20:04:59 | postgresql-client-9.1 | /usr/lib/postgresql/9.1/bin/psql | |
398 | 2013-12-16 20:08:23 | 2013-12-16 20:04:58 | postgresql-9.1 | /usr/lib/postgresql/9.1/bin/postmaster | |
452 | 2013-12-16 20:03:20 | 2013-12-16 20:04:55 | php5-dev | /usr/include/php5/main/snprintf.h | |
440 | 2013-12-16 20:03:20 | 2013-12-16 20:04:54 | php-pear | /usr/share/php/XML/Util.php |
好吧,很酷,它说我最近安装了ddd
。 和postgresql
! 我记得安装这些东西。
这里的整个消息是,如果你有一个以秒或毫秒或纳秒为单位的时间戳,那么你可以“转换”到datetime64 [the-right-thing]
,并且 pandas/numpy 将处理其余的事情。