Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么在使用Pandas';内置绘图调用,而不是通过Matplotlib?_Python_Pandas_Matplotlib - Fatal编程技术网

Python 为什么在使用Pandas';内置绘图调用,而不是通过Matplotlib?

Python 为什么在使用Pandas';内置绘图调用,而不是通过Matplotlib?,python,pandas,matplotlib,Python,Pandas,Matplotlib,我正在使用Pandas和Matlplotlib用Python绘制聚合数据。 我调用的两个类似函数中的哪一个函数用于绘制条形图,我的轴自定义命令失败。工作案例如下所示: import datetime import pandas as pd import numpy as np import matplotlib.pyplot as plt import matplotlib.dates as mdates def format_x_date_month_day(ax): days

我正在使用Pandas和Matlplotlib用Python绘制聚合数据。 我调用的两个类似函数中的哪一个函数用于绘制条形图,我的轴自定义命令失败。工作案例如下所示:

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

def format_x_date_month_day(ax):   
    days = mdates.DayLocator()
    months = mdates.MonthLocator()  # every month
    dayFmt = mdates.DateFormatter('%D')
    monthFmt = mdates.DateFormatter('%Y-%m')
    ax.figure.autofmt_xdate()
    ax.xaxis.set_major_locator(months) 
    ax.xaxis.set_major_formatter(monthFmt)
    ax.xaxis.set_minor_locator(days)

span_days = 90
start = pd.to_datetime("1-1-2012")
idx = pd.date_range(start, periods=span_days).tolist()
df=pd.DataFrame(index=idx, data={'A':np.random.random(span_days), 'B':np.random.random(span_days)})

plt.close('all')
fig, ax = plt.subplots(1)
ax.bar(df.index, df.A)      # loop over columns here to do stacked plot
format_x_date_month_day(ax)
plt.show()
(参见循环创建堆叠条形图的示例)这为我们提供了

另一种方法是使用
df.plot.bar(ax=ax,stacked=True)
,但是它不允许使用
mdates设置日期轴格式,而且更容易操作:

plt.close('all')
fig, ax = plt.subplots(1)
df.plot.bar(ax=ax, stacked=True)
format_x_date_month_day(ax)
plt.show()


如何使
mdates
ax.figure.autofmtxdate()
能够很好地使用
df.plot.bar

熊猫中的条形图设计用于比较类别,而不是显示时间序列或其他类型的连续变量,如下所述:

条形图显示离散类别之间的比较。绘图的一个轴显示正在比较的特定类别,另一个轴表示测量值

这就是为什么无论x变量的数据类型如何,条形图的x轴比例都是从零开始的整数。使用matplotlib创建同一条形图时,x轴的比例由matplotlib日期编号组成,因此可以按预期使用模块的刻度定位器和格式设置器(mdates)

若要将pandas条形图与MDATE一起使用,需要沿x轴将条形图移动到与matplotlib日期编号匹配的位置。这要归功于该功能。下面的示例根据您提供的代码进行了一些修改,说明了这一点:示例数据集包含3个变量,时间序列限制为45天,勾号格式根据我的首选项进行调整(并且没有包装为函数)

此示例适用于任意数量的变量(带或不带NaN)以及传递给pandas plot函数的任意条形宽度:

import numpy as np                   # v 1.19.2
import pandas as pd                  # v 1.1.3
import matplotlib.dates as mdates    # v 3.3.2

# Create random dataset
rng = np.random.default_rng(seed=1) # random number generator
nperiods = 45
nvar = 3
idx = pd.date_range('2012-01-01', periods=nperiods, freq='D')
df = pd.DataFrame(rng.integers(11, size=(idx.size, nvar)),
                  index=idx, columns=list('ABC'))

# Draw pandas stacked bar chart
ax = df.plot(kind='bar', stacked=True, figsize=(10,5))

# Compute width of bars in matplotlib date units
pandas_width = ax.patches[0].get_width() # the default bar width is 0.5
mdates_x0 = mdates.date2num(df.index[0])
mdates_x1 = mdates.date2num(df.index[1])
mdates_width_default = (mdates_x1-mdates_x0)/2
mdates_width = pandas_width*mdates_width_default/0.5 # rule of three conversion

# Compute new x values for bars in matplotlib date units, adjusting the
# positions according to the bar width
mdates_x = mdates.date2num(df.index) - mdates_width/2
nvar = len(ax.get_legend_handles_labels()[1])
mdates_x_patches = np.ravel(nvar*[mdates_x])

# Set bars to new x positions: this loop works fine with NaN values as
# well because in bar plot NaNs are drawn with a rectangle of 0 height
# located at the foot of the bar, you can verify this with patch.get_bbox()
for patch, new_x in zip(ax.patches, mdates_x_patches):
    patch.set_x(new_x)
    patch.set_width(mdates_width)

# Set major and minor date tick locators
months = mdates.MonthLocator()
days = mdates.DayLocator(bymonthday=np.arange(31, step=3))
ax.xaxis.set_major_locator(months)
ax.xaxis.set_minor_locator(days)

# Set major date tick formatter
month_fmt = mdates.DateFormatter('\n%b\n%Y')
day_fmt = mdates.DateFormatter('%d')
ax.xaxis.set_major_formatter(month_fmt)
ax.xaxis.set_minor_formatter(day_fmt)

# Shift the plot frame to where the bars are now located
xmin = min(mdates_x) - mdates_width
xmax = max(mdates_x) + 2*mdates_width
ax.set_xlim(xmin, xmax)

# Adjust tick label format last, else it may produce unexpected results
ax.figure.autofmt_xdate(rotation=0, ha='center')

由您决定这是否比使用matplotlib从头开始绘制堆叠条更方便

可以稍微修改此解决方案,以便根据任意时间频率为时间序列显示适当的刻度标签。下面是一个使用分钟频率、自定义栏宽度和自动日期标记定位器和格式化程序的示例。仅显示新的/修改的代码行:

import matplotlib.ticker as mtick
#...

idx = pd.date_range('2012-01-01 12', periods=nperiods, freq='T')
#...

ax = df.plot(kind='bar', stacked=True, figsize=(10,5), width=0.3)
#...

# Set adaptive tick locators and major tick formatter
maj_loc = mdates.AutoDateLocator()
ax.xaxis.set_major_locator(maj_loc)
min_loc = mtick.FixedLocator(mdates_x + mdates_width/2)
ax.xaxis.set_minor_locator(min_loc) # draw minor tick under each bar
fmt = mdates.ConciseDateFormatter(maj_loc)
ax.xaxis.set_major_formatter(fmt)
#...


您可能会注意到,刻度通常与条形图不对齐。将地物元素放在一起时,matplotlib似乎存在一些问题。我发现这通常只有在绘制比有用条更细的图时才明显。通过运行
ax.get\xticks()
并将其与
patch.get\bbox()
ax.patches

中循环时给出的值进行比较,可以检查条和记号是否确实正确放置。请提供一个工作示例,并提供数据。通过这种方式演示修复会更容易。可能与@andrew_reece的副本类似,但不是副本。注意,我通过使用
mdates
解决了该帖子关于
ax.bar(df.index,df[col_name])
的问题。然而,我的问题只存在于
df.plot.bar
中。