You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python和Matplotlib为双Y轴子图标注(数量,价格)有序对

双Y轴子图标注(y1,y2)形式有序对的问题与解决

问题说明

需为双Y轴子图标注(数量,价格)即(y1,y2)格式的标签:子图包含产品总数量柱状图、对应产品平均价格折线图,X轴为产品类别,Y1轴对应总数量,Y2轴对应平均价格。当前报错:变量label的列表元素不被识别为“可下标对象”,怀疑需将列表元素转为字符串,但不确定操作是否正确。

示例DataFrame

ProductsQuantityPrice
Product110100.00
Product215200.00
Product320150.00
Product230200.00
Product350150.00

尝试的代码

quantity = df.groupby("Products")["Quantity"].sum()
price = df.groupby("Products")["Price"].mean()

fig, ax1 = plt.subplots()
ax2 = ax1.twinx()

ax1.bar(Products, quantity, color='.8', alpha =.8)
ax2.plot(Products, price, 'bo-')

ax1.set_xlabel('', fontweight='bold')
ax1.set_ylabel('Quantity', color = 'k', fontweight='bold')
ax2.set_ylabel('Price $', color = 'b', fontweight='bold')
ax1.set_xticklabels(Products, rotation=45, size = 8)

y1 = [i for i in quantity]
y2 = [j for j in price]

label = []
for x, y in zip(y1,y2):
    label.append(f"({x:.2f},{y:.2f})")

for i, label in enumerate(labels):
    plt.annotate(label, xy=(x[i], y[i]), xytext=(5, 5),
    textcoords='offset points', ha='left', va='bottom')
plt.show()

问题区域代码

# 找不到方法在label.append()中把列表元素从float转为字符串(其实f-string已经完成转换)
label = []
for x, y in zip(y1,y2):
    label.append(f"({x:.2f},{y:.2f})")

错误原因与修正方案

核心错误点

  1. 变量名不一致:循环时用了enumerate(labels),但实际定义的列表是label,拼写错误导致“可下标对象”报错。
  2. 坐标参数错误:plt.annotate的xy参数需对应X轴位置(产品类别)和目标Y轴值(折线图的价格),原代码的x[i], y[i]完全不符合坐标逻辑。
  3. 误解字符串转换:你用的f"({x:.2f},{y:.2f})"已经自动将float转为字符串,这部分操作是正确的,无需额外处理。

修正后的完整代码

import pandas as pd
import matplotlib.pyplot as plt

# 构造示例数据
data = {
    "Products": ["Product1", "Product2", "Product3", "Product2", "Product3"],
    "Quantity": [10,15,20,30,50],
    "Price": [100.00,200.00,150.00,200.00,150.00]
}
df = pd.DataFrame(data)

# 分组计算
quantity = df.groupby("Products")["Quantity"].sum()
price = df.groupby("Products")["Price"].mean()
products = quantity.index

# 创建双Y轴子图
fig, ax1 = plt.subplots()
ax2 = ax1.twinx()

# 绘制图形
ax1.bar(products, quantity, color='.8', alpha=.8)
ax2.plot(products, price, 'bo-')

# 设置轴标签
ax1.set_xlabel('', fontweight='bold')
ax1.set_ylabel('Quantity', color='k', fontweight='bold')
ax2.set_ylabel('Price $', color='b', fontweight='bold')
ax1.set_xticklabels(products, rotation=45, size=8)

# 生成标注文本(f-string自动完成转字符串)
labels = [f"({qty:.0f}, {prc:.2f})" for qty, prc in zip(quantity, price)]

# 标注每个点
for idx, (prod, prc) in enumerate(zip(products, price)):
    ax2.annotate(labels[idx], 
                 xy=(prod, prc), 
                 xytext=(5, 5),
                 textcoords='offset points', 
                 ha='left', 
                 va='bottom')

plt.tight_layout()
plt.show()

关键修正细节

  • 统一变量命名:将列表名改为labels,确保循环时引用正确
  • 修正标注坐标:X轴用产品类别,Y轴用对应平均价格(匹配ax2的轴数据)
  • 确认字符串转换:f-string已完成数值到字符串的转换,无需额外操作

内容的提问来源于stack exchange,提问作者DerekJohn13

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 02:18:13