Boxplot放置在时间轴上

时间:2016-07-25 20:17:38

标签: python datetime pandas matplotlib boxplot

我想在时间轴上放置一系列(matplotlib)箱图。它们是在一年中的不同日期进行的一系列测量。日期不均匀分布,我对随时间的变化感兴趣。

简易版

我有一个带有索引和一系列数字的pandas DataFrame,或多或少是这样的:(注意索引):

string

对于每个索引,我需要制作一个箱形图,这没问题:

np.random.seed(12345)
data = np.array( [ np.random.normal( i, 1, 10 ) for i in range(3) ] )
ii = np.array([ 3, 5, 8 ] )
df = pd.DataFrame( data=data, index=ii )

enter image description here

时间版

问题是,我需要将方框放在时间轴上,即将方框放在具体的日期

plt.boxplot( [ df.loc[i] for i in df.index ], vert=True, positions=ii )

enter image description here

但是,如果我合并职位:

np.random.seed(12345) data = np.array( [ np.random.normal( i, 1, 10 ) for i in range(3) ] ) dates = pd.to_datetime( [ '2015-06-01', '2015-06-15', '2015-08-30' ] ) df = pd.DataFrame( data=data, index=dates ) plt.boxplot( [ df.loc[i] for i in df.index ], vert=True )

我收到错误:

  

TypeError:无法将类型'Timedelta'与'float'类型进行比较

查看文档显示:

ax.boxplot( [ df.loc[i] for i in df.index ], vert=True, positions=dates )

  

position:array-like,default = [1,2,...,n]

     

设置框的位置。刻度和限制会自动设置为与位置匹配。

希望的时间版本

此代码旨在澄清,缩小问题范围。这些框应该在那里,其中蓝点放在下一个图中。

plt.boxplot?

enter image description here

是否有方法将箱线图放在时间轴上?

我正在使用:

python:3.4.3 + numpy:1.11.0 + pandas:0.18.0 + matplotlib:1.5.1

2 个答案:

答案 0 :(得分:3)

到目前为止,我最好的解决方案是将轴的单位转换为合适的int单位并相应地绘制所有内容。就我而言,那些是天。

np.random.seed(12345)
data = np.array( [ np.random.normal( i, 1, 10 ) for i in range(3) ] )
dates = pd.to_datetime( [ '2015-06-01', '2015-06-15', '2015-08-30' ] )
df = pd.DataFrame( data=data, index=dates )

fig, ax = plt.subplots( figsize=(10,5) )
x1 = pd.to_datetime( '2015-05-01' )
x2 = pd.to_datetime( '2015-09-30' )
pos = ( dates - x1 ).days

ax.boxplot( [ df.loc[i] for i in df.index ], vert=True, positions=pos )
ax.plot( pos, [ df.loc[i].mean() for i in df.index ], 'o' )

ax.set_xlim( [ 0, (x2-x1).days ] )
ax.set_xticklabels( dates.date, rotation=45 )

enter image description here

箱形图放在正确的位置,但代码对我来说似乎有点麻烦。

更重要的是:x轴的单位不再是“时间”了。

答案 1 :(得分:2)

可以通过两种方式生成所需的输出。但是可以安全地记住GetRawInputData()boxplots的给定字段/列的y-axis绘图范围,同时保留x-axis上字段/列的名称。你可以水平绘制它们。但这个想法仍然是一样的。

无论如何,您可以使用pandas timestamp对象作为列名创建数据框。这样,当您在数据框上调用boxplot函数时,输出将显示x-axis上的列名:

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

np.random.seed(12345)
data = np.array([np.random.normal(i, 1, 50) for i in range(12)])

##Create an array that will be the names of your columns
ii = pd.date_range(pd.Timestamp('2015-06-01'),periods=data.shape[1], freq='MS')

##Create the DataFrame
df = pd.DataFrame(data=data, columns=ii)

##I am going to reduce the number of columns so that the plot can show
checker = ii[:3]
df[checker].boxplot()

#Show the boxplots. This is just for 3 columns out of 50
plt.show()

enter image description here

您也可以通过转置数据框来获取所拥有的内容,以便索引成为列名。

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

np.random.seed(12345)

data = np.array([np.random.normal(i, 1, 50) for i in range(12)])

##Create an array that will be the indices of your dataframe
ii = pd.date_range(pd.Timestamp('2015-06-01'),periods=data.shape[0], freq='MS')

##Create the DataFrame
df = pd.DataFrame(data=data, index=ii)

##I am going to reduce the number of columns so that the plot can show
checker = ii[:3]
df.T[checker].boxplot()

#Show the boxplots. This is just for 3 columns out of 50
plt.show()

enter image description here

我希望这会有所帮助。