Plotly Express:使用 px.bar() 绘制未堆叠数据框时出错

Plotly Express: error when using px.bar() to plot an unstacked data frame

我的目标是根据 Pandas 数据框中的两个过滤列创建比率,然后使用 Plotly Express 使用 px.bar() 创建条形图。我可以使用 Pandas 中的基本 plot() 函数,但不能使用 Plotly Express.

中的 px.bar() 函数

我 运行 遇到的一个问题是某些列包含重复值。这导致我不得不做一些 Pandas 体操。

这是我的数据:

test_df = pd.DataFrame({'Manufacturer':['Ford', 'Ford', 'Mercedes', 'BMW', 'Ford', 'Mercedes', 'BMW', 'Ford', 'Mercedes', 'BMW', 'Ford', 'Mercedes', 'BMW', 'Ford', 'Mercedes', 'BMW', 'Ford', 'Mercedes', 'BMW'],
                          'Metric':['Orders', 'Orders', 'Orders', 'Orders', 'Orders', 'Orders', 'Orders', 'Sales', 'Sales', 'Sales', 'Sales', 'Sales', 'Sales', 'Warranty', 'Warranty', 'Warranty', 'Warranty', 'Warranty', 'Warranty'],
                          'Sector':['Germany', 'Germany', 'Germany', 'Germany', 'USA', 'USA', 'USA', 'Germany', 'Germany', 'Germany', 'USA', 'USA', 'USA', 'Germany', 'Germany', 'Germany', 'USA', 'USA', 'USA'],
                          'Value':[45000, 70000, 90000, 65000, 40000, 65000, 63000, 2700, 4400, 3400, 3000, 4700, 5700, 1500, 2000, 2500, 1300, 2000, 2450],
                          'City': ['Frankfurt', 'Bremen', 'Berlin', 'Hamburg', 'New York', 'Chicago', 'Los Angeles', 'Dresden', 'Munich', 'Cologne', 'Miami', 'Atlanta', 'Phoenix', 'Nuremberg', 'Dusseldorf', 'Leipzig', 'Houston', 'San Diego', 'San Francisco']
                       })

由于一些重复的值,我创建了一个临时的 table:

temp_table = test_df.reset_index().pivot_table(values = 'Value', index = ['Manufacturer', 'Metric', 'Sector'], aggfunc='sum')

然后,重置索引:

df_new = temp_table.reset_index()

然后,

s1 = df_new.set_index(['Manufacturer','Sector']).query("Metric=='Orders'").Value
s2 = df_new.set_index(['Manufacturer','Sector']).query("Metric=='Sales'").Value

然后,展开并绘图:

temp_frame = s1.div(s2).unstack()
temp_frame.plot(kind='bar')

这非常有效,并使用标准 Pandas plot() 函数生成以下条形图:

现在,我尝试在 Plotly Express 中使用 px.bar() 函数进行绘图:

px.bar(temp_frame, x='Sector', y='Value', color='Exchange',
                            barmode='group',
                            text='Value',
                            title='Order to Sales Ratio)

此代码导致以下错误消息:

ValueError: Value of 'x' is not the name of a column in 'data_frame'. Expected one of ['Germany', 'USA'] but received: Sector

此错误看起来与 中报告的问题有关。但是,我认为我的数据框的配置方式无法实现 @Laurens Koppenol 建议并由 @nicolaskruchten 验证的 "ugly fix" 解决方案.

谁能帮我解决这个错误,这样我就可以使用 Plotly Express?

创建上面的条形图

提前致谢!

Plotly 4.8 版允许我们这样做!

https://community.plotly.com/t/announcing-plotly-py-4-8-plotly-express-support-for-wide-and-mixed-form-data-plus-a-pandas-backend/40048

根据文档:

"...Plotly Express 现在可以在相应函数的 x 和 y 参数方面表现得更像默认的 Pandas 绘图后端。鉴于此,我们正在利用 Pandas v0.25 中引入的新 pandas.options.plotting.backend 选项,并为 Pandas 绘图提供官方 plotly 后端。这意味着您可以将 Pandas 导入为通常,将绘图后端设置为 "plotly",当您调用 df.plot() 时,将调用 Plotly Express,并返回一个 plotly.graph_objects.Figure 对象,准备好进行自定义、渲染,或传递到 Dash Core Components 的图形组件。"

这样做的代码是:

import pandas as pd
pd.options.plotting.backend='plotly'

test_df = pd.DataFrame({'Manufacturer':['Ford', 'Ford', 'Mercedes', 'BMW', 'Ford', 'Mercedes', 'BMW', 'Ford', 'Mercedes', 'BMW', 'Ford', 'Mercedes', 'BMW', 'Ford', 'Mercedes', 'BMW', 'Ford', 'Mercedes', 'BMW'],
                          'Metric':['Orders', 'Orders', 'Orders', 'Orders', 'Orders', 'Orders', 'Orders', 'Sales', 'Sales', 'Sales', 'Sales', 'Sales', 'Sales', 'Warranty', 'Warranty', 'Warranty', 'Warranty', 'Warranty', 'Warranty'],
                          'Sector':['Germany', 'Germany', 'Germany', 'Germany', 'USA', 'USA', 'USA', 'Germany', 'Germany', 'Germany', 'USA', 'USA', 'USA', 'Germany', 'Germany', 'Germany', 'USA', 'USA', 'USA'],
                          'Value':[45000, 70000, 90000, 65000, 40000, 65000, 63000, 2700, 4400, 3400, 3000, 4700, 5700, 1500, 2000, 2500, 1300, 2000, 2450],
                          'City': ['Frankfurt', 'Bremen', 'Berlin', 'Hamburg', 'New York', 'Chicago', 'Los Angeles', 'Dresden', 'Munich', 'Cologne', 'Miami', 'Atlanta', 'Phoenix', 'Nuremberg', 'Dusseldorf', 'Leipzig', 'Houston', 'San Diego', 'San Francisco']
                       })


temp_table = test_df.reset_index().pivot_table(values = 'Value', index = ['Manufacturer', 'Metric', 'Sector'], aggfunc='sum')


df_new = temp_table.reset_index()


s1 = df_new.set_index(['Manufacturer','Sector']).query("Metric=='Orders'").Value
s2 = df_new.set_index(['Manufacturer','Sector']).query("Metric=='Sales'").Value

temp_frame = s1.div(s2).unstack()


fig = temp_frame.plot(kind='bar')
fig.update_layout(barmode='group')
fig.show()