python - Altair条形图具有可变宽度的条形?
问题描述
我正在尝试在 Python 中使用 Altair 制作一个条形图,其中条形的宽度取决于源数据框列中的数据。最终目标是得到这样的图表:
条形的高度对应于每种能源技术的边际成本(在源数据框中以列形式给出)。条形宽度对应于每种能源技术的容量(也在源数据框中以列的形式给出)。颜色也是来自源数据框的序数数据。条形按边际成本的升序排序。(这样的情节在能源行业被称为“发电堆栈”)。这在 matplotlib 中很容易实现,如下面的代码所示:
import matplotlib.pyplot as plt
# Make fake dataset
height = [3, 12, 5, 18, 45]
bars = ('A', 'B', 'C', 'D', 'E')
# Choose the width of each bar and their positions
width = [0.1,0.2,3,1.5,0.3]
y_pos = [0,0.3,2,4.5,5.5]
# Make the plot
plt.bar(y_pos, height, width=width)
plt.xticks(y_pos, bars)
plt.show()
(来自https://python-graph-gallery.com/5-control-width-and-space-in-barplots/的代码)
但是有没有办法用 Altair 做到这一点?我想用 Altair 来做这件事,这样我仍然可以获得 Altair 的其他强大功能,例如工具提示、选择器/绑定,因为我有很多其他数据想要在条形图旁边显示。
我的源数据的前 20 行如下所示:
(与上面显示的图表不完全匹配)。
解决方案
在 Altair 中,执行此操作的方法是使用rect
标记并显式构建您的条形图。这是一个模仿您的数据的示例:
import altair as alt
import pandas as pd
import numpy as np
np.random.seed(0)
df = pd.DataFrame({
'MarginalCost': 100 * np.random.rand(30),
'Capacity': 10 * np.random.rand(30),
'Technology': np.random.choice(['SOLAR', 'THERMAL', 'WIND', 'GAS'], 30)
})
df = df.sort_values('MarginalCost')
df['x1'] = df['Capacity'].cumsum()
df['x0'] = df['x1'].shift(fill_value=0)
alt.Chart(df).mark_rect().encode(
x=alt.X('x0:Q', title='Capacity'),
x2='x1',
y=alt.Y('MarginalCost:Q', title='Marginal Cost'),
color='Technology:N',
tooltip=["Technology", "Capacity", "MarginalCost"]
)
要在不预处理数据的情况下获得相同的结果,可以使用 Altair 的转换语法:
df = pd.DataFrame({
'MarginalCost': 100 * np.random.rand(30),
'Capacity': 10 * np.random.rand(30),
'Technology': np.random.choice(['SOLAR', 'THERMAL', 'WIND', 'GAS'], 30)
})
alt.Chart(df).transform_window(
x1='sum(Capacity)',
sort=[alt.SortField('MarginalCost')]
).transform_calculate(
x0='datum.x1 - datum.Capacity'
).mark_rect().encode(
x=alt.X('x0:Q', title='Capacity'),
x2='x1',
y=alt.Y('MarginalCost:Q', title='Marginal Cost'),
color='Technology:N',
tooltip=["Technology", "Capacity", "MarginalCost"]
)
推荐阅读
- java - 如何将图像和文档同时上传到 Firebase 存储,获取下载 URL 并将它们同时插入实时数据库?
- jquery - 使用 AJAX 调用从 API 获取数据的变量
- date - Power BI 汇率计算
- python - 如何根据我的代码输出在 jupyter notebook 中创建文本文件
- php - 在 PHP 中加入多个 json 文件的最有效方法
- node.js - PUT 在 POSTMAN 上不起作用,但从前端调用时可以
- java - 将两位数年份转换为四位数字,还支持一位或两位数月份
- calculated-columns - Spotfire - 基于 Spotfire 中另一列中的值计算的列
- python-3.x - ModuleNotFoundError 没有名为 onetimepad 的模块?
- c# - 当控件已经获得焦点时触发屏幕阅读器