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

Matplotlib Mplot3d plot_surface报错:'list'无'ndim'属性求助

解决plot_surface的AttributeError及代码逻辑问题

首先,咱们先拆解你遇到的问题:AttributeError: 'list' object has no attribute 'ndim'是因为matplotlib的plot_surface函数要求Z必须是二维numpy数组,但你现在传入的Z是一维列表,同时你的循环逻辑还有几个小错误,导致数据结构完全不符合3D绘图的要求。

问题点逐一修复

  1. 循环逻辑错误

    • 内层循环你写的是for j in (0,80,5),这是一个只有3个元素的元组,不是你想要的从0到80步长5的序列,应该改成range(0,80,5)。
    • 内层循环里你把NH4的 uptake设成了-i,这会导致内层循环中NH4的取值不会变化,应该改成-j。
    • 每次修改反应的上下界后,你没有重新调用model.optimize(),所以solution.f一直是最开始的计算结果,不会随边界变化更新。
  2. Z数组结构错误
    当前你的growth_rate是一维列表,但meshgrid生成的X和Y是二维数组,所以Z必须是对应的二维结构。我们可以把growth_rate改成二维列表,每次内层循环结束后,把当前这一组的生长率添加进去,最后再转成numpy数组。

修改后的完整代码

import cobra
import os
from os.path import join
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D

data_dir ='/Users/stephenchapman/Documents/research/FBA_algae_digesate/COBRApy/iCZ843/iCZ843_models'
model = cobra.io.read_sbml_model(join(data_dir, "iCZ843_hetero.xml"))

# 设置反应边界
model.reactions[15].upper_bound = 0 #ammonia
model.reactions[15].lower_bound = -98.3
model.reactions[27].upper_bound = 0 #acetate
model.reactions[27].lower_bound = -3.3
model.reactions[14].upper_bound = 0 #phosphate
model.reactions[14].lower_bound = -10
model.reactions[16].upper_bound = 0 #nitrate
model.reactions[16].lower_bound = -30.3
model.reactions[20].upper_bound = 0 #magnesium
model.reactions[20].lower_bound = -0.56
model.reactions[18].upper_bound = 0 #iron
model.reactions[18].lower_bound = -2.16

model.objective = model.reactions[63]
# 先优化一次初始状态
solution = model.optimize()
model.summary()

# 改成二维列表存储生长率
growth_rate = []
ac_uptake_range = range(0,85,5)
nh4_uptake_range = range(0,80,5)

for i in ac_uptake_range:
    # 设置acetate的uptake
    model.reactions[27].lower_bound = -i
    model.reactions[27].upper_bound = -i
    # 存储当前acetate对应的所有生长率
    current_growth = []
    for j in nh4_uptake_range:
        # 设置NH4的uptake,这里用j而不是i!
        model.reactions[15].lower_bound = -j
        model.reactions[15].upper_bound = -j
        # 重新优化模型
        solution = model.optimize()
        current_growth.append(solution.f)
    # 将当前组的生长率添加到二维列表
    growth_rate.append(current_growth)

# 转换为numpy数组
X, Y = np.meshgrid(list(ac_uptake_range), list(nh4_uptake_range))
Z = np.array(growth_rate)

fig = plt.figure()
ax = Axes3D(fig)
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.viridis)
# 可以加上轴标签让图更清晰
ax.set_xlabel('Acetate Uptake')
ax.set_ylabel('NH4 Uptake')
ax.set_zlabel('Growth Rate')
plt.show()

额外说明

  • 我把ac_uptake和NH4_uptake的列表换成了直接用range对象,这样更简洁,也避免重复创建列表。
  • 添加了轴标签,让你的3D图更容易理解。
  • 注意我把反应的upper_bound从-0改成了0,因为-0和0在数值上没有区别,这样写更规范。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 10:04:53