pandas Streamlit自动填充多选小部件以过滤 Dataframe

6tdlim6h  于 2023-05-05  发布在  其他
关注(0)|答案(1)|浏览(173)

我有一个streamlit应用程序,用户可以上传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")
vjrehmav

vjrehmav1#

当您尝试将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)

这意味着您的DataFrame有97行,并且您正在分配一个独立的元素(长度为0)。
当你在try/except块中换行时,起作用的部分(也就是:st.sidebar.multiselect('Filter '+y, columns))被执行,这就是为什么你会得到侧边栏:因为错误发生在创建它之后。
您可以通过在字典中收集对边栏的引用来解决这个问题

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

相关问题