我想在时间轴上放置一系列(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 )
问题是,我需要将方框放在时间轴上,即将方框放在具体的日期
plt.boxplot( [ df.loc[i] for i in df.index ], vert=True, positions=ii )
但是,如果我合并职位:
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?
是否有方法将箱线图放在时间轴上?
我正在使用:
python:3.4.3 + numpy:1.11.0 + pandas:0.18.0 + matplotlib:1.5.1
答案 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 )
箱形图放在正确的位置,但代码对我来说似乎有点麻烦。
更重要的是: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()
您也可以通过转置数据框来获取所拥有的内容,以便索引成为列名。
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()
我希望这会有所帮助。