Matplotlib pandas 以日期时间为索引的季度条形图不工作
Matplotlib pandas Quarterly bar chart with datetime as index not Working
我有一个索引为 datetime 的 pandas 系列,我正在尝试对其进行可视化,
使用条形图。我的代码如下。但是我得到的图表似乎不太准确(下图)。我该如何解决?
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(100)
dti = pd.date_range('2012-12-31', periods=30, freq='Q')
s2 = pd.Series(np.random.randint(100,1000,size=(30)),index=dti)
df4 = s2.to_frame(name='count')
print('\ndf4:')
print(df4)
print(type(df4))
f2 = plt.figure("Quarterly",figsize=(10,5))
ax = plt.subplot(1,1,1)
ax.bar(df4.index,df4['count'])
plt.tight_layout()
plt.show()
您可以通过 ax.bar()
中的 width
参数将条形宽度设置为大于 0.8
默认值的某个值
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(100)
dti = pd.date_range('2012-12-31', periods=30, freq='Q')
s2 = pd.Series(np.random.randint(100,1000,size=(30)),index=dti)
df4 = s2.to_frame(name='count')
f2 = plt.figure("Quarterly",figsize=(10,5))
ax = plt.subplot(1,1,1)
ax.bar(df4.index,df4['count'], width=70)
plt.tight_layout()
plt.show()
在这种情况下,宽度被解释为以天为单位的标量。
编辑
出于某种原因,以上仅适用于旧版本的 matplotlib(已测试 2.2.3)。为了使用当前 (3.1.2) 版本,必须进行以下修改:
# ...
dti = pd.date_range('2012-12-31', periods=30, freq='Q')
dti = [pd.to_datetime(t) for t in dti]
# ...
这将在设置条形宽度时产生正确的行为。
不幸的是,matplotlib 的条形图似乎不太适合 pandas 日期。
理论上,matplotlib 以天数表示条形宽度。但是如果你尝试像 ax.bar(df4.index,df4['count'], width=30)
这样的东西,你会看到带有非常宽条的图,几乎完全填满了图。用 width
做试验,奇怪的事情发生了。当width
小于2的时候,貌似是用天来表示的。但是当 width
大于 2 时,它突然跳到更宽的范围。
在我的系统上(matplotlib 3.1.2,pandas 0.25.3,Windows)它看起来像:
解决方法是使用 pandas 中的条形图。这些似乎使柱状图明确化,每个柱状图有一个刻度。 但是它们会被标记为包含小时、分钟和秒的完整日期。您可以重新标记它们,例如:
df4.plot.bar(y='count', width=0.9, ax=ax)
plt.xticks(range(len(df4.index)),
[t.to_pydatetime().strftime("%b '%y") for t in df4.index],
rotation=90)
进一步调查,matplotlib 条形宽度的不一致跳跃似乎与 frequency
构建到 pandas 次有关。因此,解决方案可能是将日期转换为 matplotlib 日期。试试这个,是的,宽度在几天内得到一致的表达。
不幸的是,季度日期之间的天数并不完全相同,导致一些条形太宽,而另一些则太窄。下一个问题的解决方案是明确计算每个柱的天数。为了在条形之间获得很好的分离,将它们的边缘绘制成白色会有所帮助。
from datetime import datetime
x = [datetime.date(t) for t in df4.index] # convert the pandas datetime to matplotlib's
widths = [t1-t0 for t0, t1 in zip(x, x[1:])] # time differences between dates
widths += [widths[-1]] # the very last bar didn't get a width, just repeat the last width
ax.bar(x, df4['count'], width=widths, edgecolor='white')
我有一个索引为 datetime 的 pandas 系列,我正在尝试对其进行可视化,
使用条形图。我的代码如下。但是我得到的图表似乎不太准确(下图)。我该如何解决?
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(100)
dti = pd.date_range('2012-12-31', periods=30, freq='Q')
s2 = pd.Series(np.random.randint(100,1000,size=(30)),index=dti)
df4 = s2.to_frame(name='count')
print('\ndf4:')
print(df4)
print(type(df4))
f2 = plt.figure("Quarterly",figsize=(10,5))
ax = plt.subplot(1,1,1)
ax.bar(df4.index,df4['count'])
plt.tight_layout()
plt.show()
您可以通过 ax.bar()
中的 width
参数将条形宽度设置为大于 0.8
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
np.random.seed(100)
dti = pd.date_range('2012-12-31', periods=30, freq='Q')
s2 = pd.Series(np.random.randint(100,1000,size=(30)),index=dti)
df4 = s2.to_frame(name='count')
f2 = plt.figure("Quarterly",figsize=(10,5))
ax = plt.subplot(1,1,1)
ax.bar(df4.index,df4['count'], width=70)
plt.tight_layout()
plt.show()
在这种情况下,宽度被解释为以天为单位的标量。
编辑
出于某种原因,以上仅适用于旧版本的 matplotlib(已测试 2.2.3)。为了使用当前 (3.1.2) 版本,必须进行以下修改:
# ...
dti = pd.date_range('2012-12-31', periods=30, freq='Q')
dti = [pd.to_datetime(t) for t in dti]
# ...
这将在设置条形宽度时产生正确的行为。
不幸的是,matplotlib 的条形图似乎不太适合 pandas 日期。
理论上,matplotlib 以天数表示条形宽度。但是如果你尝试像 ax.bar(df4.index,df4['count'], width=30)
这样的东西,你会看到带有非常宽条的图,几乎完全填满了图。用 width
做试验,奇怪的事情发生了。当width
小于2的时候,貌似是用天来表示的。但是当 width
大于 2 时,它突然跳到更宽的范围。
在我的系统上(matplotlib 3.1.2,pandas 0.25.3,Windows)它看起来像:
解决方法是使用 pandas 中的条形图。这些似乎使柱状图明确化,每个柱状图有一个刻度。 但是它们会被标记为包含小时、分钟和秒的完整日期。您可以重新标记它们,例如:
df4.plot.bar(y='count', width=0.9, ax=ax)
plt.xticks(range(len(df4.index)),
[t.to_pydatetime().strftime("%b '%y") for t in df4.index],
rotation=90)
进一步调查,matplotlib 条形宽度的不一致跳跃似乎与 frequency
构建到 pandas 次有关。因此,解决方案可能是将日期转换为 matplotlib 日期。试试这个,是的,宽度在几天内得到一致的表达。
不幸的是,季度日期之间的天数并不完全相同,导致一些条形太宽,而另一些则太窄。下一个问题的解决方案是明确计算每个柱的天数。为了在条形之间获得很好的分离,将它们的边缘绘制成白色会有所帮助。
from datetime import datetime
x = [datetime.date(t) for t in df4.index] # convert the pandas datetime to matplotlib's
widths = [t1-t0 for t0, t1 in zip(x, x[1:])] # time differences between dates
widths += [widths[-1]] # the very last bar didn't get a width, just repeat the last width
ax.bar(x, df4['count'], width=widths, edgecolor='white')