【问题标题】:Streamlit auto populate multiselect widgets to filter dataframeStreamlit 自动填充多选小部件以过滤数据框
【发布时间】:2021-05-09 07:57:09
【问题描述】:

我有一个流线型应用程序,用户可以在其中上传 csv 文件。我希望 streamlit 检测对象/维度列,并为每个列创建一个多选过滤器,并在每个列内使用唯一值。例如,如果用户上传具有 3 个对象/维度的文件,则会创建 3 个单独的多选过滤器。我想出了下面的代码,但它似乎不起作用。我最终得到以下错误。我认为问题是循环创建每个多选过滤器,但我不确定另一种动态执行此操作的方法。我也试过用data[y].unique() 代替ucolumns,但这仍然不起作用。

任何帮助都会很棒。

        for y in data.columns:
            if (data[y].dtype == np.object):
                ucolumns=list(data[y].unique())
                data[y+"filter"]=st.sidebar.multiselect('Filter '+y, ucolumns)
            else:
                pass
ValueError: Length of values (0) does not match length of index (97)
File "c:\users\###\pycharmprojects\pythonproject\venv\lib\site-packages\streamlit\script_runner.py", line 332, in _run_script
    exec(code, module.__dict__)
File "C:\Users\###\PycharmProjects\pythonProject\streamlittest.py", line 109, in <module>
    helper.run()
File "C:\Users\###\PycharmProjects\pythonProject\streamlittest.py", line 66, in run
    data[y+"filter"]=st.sidebar.multiselect('Filter '+y, ucolumns)
File "c:\users\###\pycharmprojects\pythonproject\venv\lib\site-packages\pandas\core\frame.py", line 3163, in __setitem__
    self._set_item(key, value)
File "c:\users\###\pycharmprojects\pythonproject\venv\lib\site-packages\pandas\core\frame.py", line 3239, in _set_item
    value = self._sanitize_column(key, value)
File "c:\users\###\pycharmprojects\pythonproject\venv\lib\site-packages\pandas\core\frame.py", line 3896, in _sanitize_column
    value = sanitize_index(value, self.index)
File "c:\users\###\pycharmprojects\pythonproject\venv\lib\site-packages\pandas\core\internals\construction.py", line 751, in sanitize_index
    raise ValueError(

测试一些东西,我将多选包装在 try 和 except 中,打印 y 以查看哪些列进入异常。似乎所有维度列都进入了例外,但奇怪的是所有多选都被创建并且似乎工作?谁能向我解释发生了什么事?这是我所做的调整:

try:
    data[y+"filter"]=st.sidebar.multiselect('Filter '+y, ucolumns)
except:
    print(y+"had to pass")

【问题讨论】:

    标签: python pandas loops streamlit


    【解决方案1】:

    当您尝试将 streamlit 侧边栏分配给 pandas 的 DataFrame 列时会出现问题。

    这就是为什么,当您允许使用 try/except 块继续执行时,会设置侧边栏,但无论如何都会引发异常。

    换句话说,如果您将有问题的行一分为二,您将得到以下结果:

    sidebar = st.sidebar.multiselect('Filter '+y, columns) # <-- This line is OK
    data[y+"filter"] = sidebar # <-- This line fails
    

    该行失败,因为 data 是 pandas 的 DataFrame,因此 data[y+'filter'] 是一列。而且您不能将一个元素分配给一列,这是非常神秘的错误消息中所述:

    ValueError: Length of values (0) does not match length of index (97)
    

    这意味着您的数据框有 97 行,并且您正在分配一个独立元素(“长度为 0”)。

    当您将行包装在 try/except 块中时,有效的部分(又名:st.sidebar.multiselect('Filter '+y, columns))会被执行,这就是您获得侧边栏的原因:因为错误发生在 之后创建它。

    您可以通过在字典中收集对侧边栏的引用来解决问题

    sidebars = {}
    for y in data.columns:
        if (data[y].dtype == np.object):
            ucolumns=list(data[y].unique())
            sidebars[y+"filter"]=st.sidebar.multiselect('Filter '+y, ucolumns)
    

    【讨论】:

    • 感谢dataista!完美的解释。现在创建了这些过滤器,动态过滤数据框的最佳方法是什么?假设它仍然必须在 for 循环中完成?
    • 我似乎在这个 anwser stackoverflow.com/questions/52714316/… 的帮助下解决了这个问题,再次感谢 dataisata!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 2014-12-14
    • 1970-01-01
    • 2021-11-04
    • 1970-01-01
    • 1970-01-01
    • 2020-09-17
    相关资源
    最近更新 更多