具有适当轴标记的datetime64 [ns]类型的数据的直方图

时间:2017-06-20 12:44:09

标签: python pandas numpy matplotlib histogram

我正在将csv文件加载到pandas数据帧中。我想绘制结果数据的直方图。

我的一些专栏是日期。 Pandas使用数据类型datetime64 [ns]来存储它们。对于我的日期,我想在x轴上放置正确的日期格式化x刻度标记。

以下是一些不起作用的代码:

import pandas
import numpy as np
import os
from datetime import datetime
from matplotlib import pyplot as plt

dirname='/my_working_dir/'
in_filename=os.path.join(dirname,'input_data.csv')
df = pandas.read_csv(in_filename,parse_dates=['Date of event'],dayfirst=True)

failures=df[df['Failure']==True];
suspensions=df[df['Failure']==False];

f=failures['Date of event'].dropna()
s=suspensions['Date of event'].dropna()

fig, ax = plt.subplots()
ax.hist([f,s],40,weights=[np.zeros_like(f) + 1. / f.size,
                         np.zeros_like(s) + 1. / s.size],
        color=['r','g']);
ax.set_yticklabels(['{:.0f}%'.format(x*100) 
                           for x in plt.gca().get_yticks()])
numbers=ax.get_xticks();
labels=map(lambda x: datetime.fromtimestamp(x).strftime('%Y-%m-%d'), numbers)
plt.xticks(numbers, labels)

错误:

Traceback (most recent call last):
   File "datetest.py", line 22, in <module>
    ax.hist([f,s],40,weights=[np.zeros_like(f) + 1. / f.size,
TypeError: ufunc add cannot use operands with types dtype('<M8[ns]') and dtype('float64')

我知道这是相当多的代码,但问题在于整合整个事情,我愿意更改任何部分(读取数据,或绘图,或设置xlabels)以获得它工作

我尝试过的事情:

  • 使用df['int_date']=df['Date of event'].view('int64')制作日期数据的整数版本。这让我可以绘制出我需要的直方图。 x的范围是1e18到1.5e18,我无法弄清楚如何获得正确的日期格式xticks。
  • 尝试使用df['test']=((df['Date of event'] - np.datetime64('1970-01-01T00:00:00Z')) / np.timedelta64(1, 's'))转换为时间戳(如另一个堆栈溢出帖子中所示)我得到:“TypeError:输入类型不支持ufunc'isnan',并且无法安全地强制输入根据投射规则''safe''任何支持的类型“我的numpy是版本1.10.4,我无法在我的系统上安装新库或升级。

以下是csv文件的一些简化内容(我的实际数据要大得多):

Index,Date of event,Failure
12421,18/11/2016,TRUE
12409,01/05/2017,FALSE
12410,29/03/2017,FALSE
12453,21/08/2016,TRUE
12454,01/08/2016,TRUE

How can I convert pandas date time xticks to readable format?中的答案并没有解决我的问题 - 我甚至无法使用我的数据的情节仍处于datetime64格式。在那个问题中,有工作xticks,但他们只需要重新格式化。

感谢您提供任何帮助。

1 个答案:

答案 0 :(得分:2)

你有两个问题。

第一个是weights列表。 np.zeros_like(f)不会给出任何有用的东西,因为首先,f是一个系列,而不是一个numpy数组,第二,它由日期组成,但是日期方面的零是什么?
你真正想要的是一个零的数组,其长度与f相同。这可以通过np.zeros(len(f))np.zeros(f.size)获得。

其次,你不能直接使用该系列,但需要取其值:ax.hist([f.values, s.values])而不是ax.hist([f, s])

所以总的来说:

weights = [np.zeros(len(f)) + 1. / f.size,  np.zeros(len(s)) + 1. / s.size]
ax.hist([f.values, s.values],40,weights=weights, color=['r','g'])

此时您可能会考虑格式化x轴,但是,这会导致新的错误,因此我建议将其保留,如果需要,请坚持使用类似于此问题中提供的解决方案{{3 }}

一个完整的例子:

import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import numpy as np

dates = pd.date_range("2013-01-01", "2017-06-20" )
y = np.cumsum(np.random.normal(size=len(dates)))
fail = np.random.choice([True, False], size=len(dates))

df = pd.DataFrame({'Date of event':dates, "y":y, 'Failure':fail})

failures=df[df['Failure']==True];
suspensions=df[df['Failure']==False];

f=failures['Date of event'].dropna()
s=suspensions['Date of event'].dropna()

fig, ax = plt.subplots()

weights=[np.zeros(len(f)) + 1. / f.size,  np.zeros(len(s)) + 1. / s.size]
ax.hist([f.values, s.values],40,weights=weights,
        color=['r','g'])


ax.set_yticklabels(['{:.1f}%'.format(x*100) 
                           for x in plt.gca().get_yticks()])
fig.autofmt_xdate()
plt.show()

How can I convert pandas date time xticks to readable format?