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

使用rpy2+Streamlit构建应用时的PCA可视化报错求助

问题:Streamlit中使用rpy2调用R的FactoMineR绘制PCA方差直方图报错

我尝试用Python和rpy2构建应用,读取名为table_mean_plain.csv的文件后绘制PCA解释方差百分比的直方图,代码在Jupyter Notebook中运行正常,但在Streamlit中加载超时,且出现如下报错:

2022-10-25 17:08:05.231 Uncaught app exception
Traceback (most recent call last):
  File "/opt/anaconda3/envs/XX/lib/python3.9/site-packages/streamlit/runtime/scriptrunner/script_runner.py", line 562, in _run_script
    exec(code, module.__dict__)
  File "/Users/XX/Documents/XX/pages/4_Visualisations.py", line 69, in <module>
    res_pca = FactoMineR.PCA(my_data)
  File "/opt/anaconda3/envs/XX/lib/python3.9/site-packages/rpy2/robjects/functions.py", line 201, in __call__
    return (super(SignatureTranslatedFunction, self)
  File "/opt/anaconda3/envs/XX/lib/python3.9/site-packages/rpy2/robjects/functions.py", line 124, in __call__
    res = super(Function, self).__call__(*new_args, **new_kwargs)
  File "/opt/anaconda3/envs/XX/lib/python3.9/site-packages/rpy2/rinterface_lib/conversion.py", line 45, in _
    cdata = function(*args, **kwargs)
  File "/opt/anaconda3/envs/XX/lib/python3.9/site-packages/rpy2/rinterface.py", line 810, in __call__
    raise embedded.RRuntimeError(_rinterface._geterrmessage())
rpy2.rinterface_lib.embedded.RRuntimeError: 在函数(...)中出错:无法创建目标设备quartz(),提供的类型可能不被支持

Assertion failed: (NSViewIsCurrentlyBuildingLayerTreeForDisplay() != currentlyBuildingLayerTree), function NSViewSetCurrentlyBuildingLayerTreeForDisplay, file NSView.m, line 13477.
[9]    59974 illegal hardware instruction  streamlit run 1_Workbench.py

原代码

from rpy2.robjects.packages import importr, data
from rpy2.robjects.vectors import DataFrame
from rpy2.ipython.ggplot import image_png
import streamlit as st
import matplotlib.pyplot as plt
from rpy2 import robjects

import matplotlib.image as mpimg


utils = importr('utils')
corrplot = importr('corrplot')
FactoMineR = importr('FactoMineR')
factoextra = importr('factoextra')

my_datafile = 'table/plain/table_mean_plain.csv'

#my_data = utils.read_csv(my_datafile)

my_data = DataFrame.from_csvfile(my_datafile, row_names="X")
#rownames(my_data = my_data$X
#my_dataX = NULL

# Do PCA
# --------
res_pca = FactoMineR.PCA(my_data)

# Eigen values / Variance
# --------
eig_val = factoextra.get_eigenvalue(res_pca)
st.pyplot(display(image_png(factoextra.fviz_eig(res_pca, addlabels = True))))

对应的CSV文件内容

,logistic-regression,svm-linear,svm-rbf,Gnb,decision-tree,random-forest,XGBoost,MLP,Ensemble,GEV,iForest,DevNet
news,0.827,0.566,0.724,0.681,0.687,0.852,0.865,0.859,0.866,0.87,0.497,0.666
telE,0.761,0.552,0.623,0.756,0.86,0.944,0.957,0.915,0.95,0.941,0.399,0.717
bank,0.832,0.62,0.772,0.817,0.687,0.848,0.841,0.848,0.855,0.873,0.625,0.793
member,0.648,0.488,0.514,0.625,0.574,0.696,0.695,0.669,0.707,0.667,0.545,0.598
dsn,0.735,0.708,0.785,0.707,0.761,0.884,0.897,0.754,0.884,0.766,0.568,0.661
mobile,0.889,0.432,0.393,0.842,0.776,0.9,0.906,0.9,0.908,0.907,0.7,0.852
campaign,0.907,0.543,0.668,0.809,0.709,0.928,0.933,0.923,0.935,0.924,0.65,0.832
HR,0.85,0.766,0.841,0.762,0.615,0.809,0.797,0.825,0.838,0.827,0.589,0.72
sato,0.794,0.747,0.8,0.729,0.651,0.808,0.809,0.799,0.825,0.82,0.5,0.739
uci,0.854,0.586,0.897,0.859,0.818,0.901,0.905,0.847,0.913,0.91,0.663,0.793
TelC,0.844,0.632,0.797,0.814,0.658,0.819,0.825,0.842,0.841,0.85,0.295,0.784
median_AUC,0.832,0.586,0.772,0.762,0.687,0.852,0.866,0.847,0.866,0.87,0.568,0.739
Rank,5.67,10.67,7.5,8.08,9.0,4.0,3.25,5.0,1.83,2.67,11.42,8.92

问题原因

报错核心是R在Streamlit的无GUI服务器环境下无法创建默认的quartz绘图设备:Jupyter Notebook运行在有桌面GUI的交互式环境中,支持quartz设备;但Streamlit是服务器端运行,没有桌面图形环境,导致R无法初始化绘图设备,进而触发报错。

修复方案

1. 配置R使用非交互式绘图设备

在代码开头添加配置,强制R使用适用于无GUI环境的png设备(底层基于Agg),避免quartz设备的依赖:

from rpy2 import robjects
robjects.r('''
options(device = "png")
''')

2. 调整Streamlit的图像显示逻辑

原代码中st.pyplot(display(image_png(...)))的用法错误:display()是IPython的交互显示函数,Streamlit不支持;直接用st.image()接收image_png()返回的字节流即可正确显示图像。

3. 可选:改用Pandas读取数据(提升兼容性)

rpy2内置的DataFrame.from_csvfile在部分场景下存在兼容性问题,改用Pandas读取CSV后转为R对象,稳定性更好:

import pandas as pd
from rpy2.robjects import pandas2ri
pandas2ri.activate()

df = pd.read_csv(my_datafile, index_col=0)
my_data = pandas2ri.py2rpy(df)

修改后的完整代码

from rpy2.robjects.packages import importr
from rpy2.ipython.ggplot import image_png
import streamlit as st
from rpy2 import robjects
import pandas as pd
from rpy2.robjects import pandas2ri

# 激活Pandas与R对象的转换
pandas2ri.activate()

# 设置R使用非交互式绘图设备,避免quartz报错
robjects.r('''
options(device = "png")
''')

# 导入所需R包
FactoMineR = importr('FactoMineR')
factoextra = importr('factoextra')

my_datafile = 'table/plain/table_mean_plain.csv'

# 用Pandas读取CSV并转为R的DataFrame
df = pd.read_csv(my_datafile, index_col=0)
my_data = pandas2ri.py2rpy(df)

# 执行PCA分析
res_pca = FactoMineR.PCA(my_data)

# 生成方差解释直方图并在Streamlit中显示
img_bytes = image_png(factoextra.fviz_eig(res_pca, addlabels = True))
st.image(img_bytes)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 10:00:55