Streamlit、Python 和 Pandas:重复键和写入

Streamlit, Python, and Pandas: Duplicate keys and writing

借助 Python 和 Streamlit,我正在构建应用程序来帮助教师对论文进行评分。在应用程序的这一部分中,用户将获得所有学生提交的 .txt 文件。这些文件显示在主屏幕上,用户向下滚动以显示其他文本。在边栏中有输入字段,用于输入每个单独的 txt 的评论和等级。该应用程序的布局如下:

到目前为止一切顺利。但是,我不知道如何使用 pandas 将侧边栏单选按钮的输出和数字输入捕获到 csv 中。下面是我的工作代码:

import os
import streamlit as st
import pandas as pd

# for establishing length of loops below
path, dirs, files = next(os.walk("TXTs"))
float_file_count = ((len(files)) / 3)
file_count = int(float_file_count)

txts = [f"TXTs\feedback_{n}.txt" for n in range(file_count)]


#streamlit layout
st.set_page_config(layout="wide")
st.sidebar.header("Grading Interface")
button1 = st.sidebar.button("Record comments and grades.")
st.header("Demo - Level 3.6.2 (Prototype)")
st.subheader("In this level...")

# loop to display txt files in main screen
def display_txts():
    for txt in txts:
        with open(txt, 'r', encoding="utf8") as infile:
            contents = infile.read()
            st.markdown(":point_right:  " + "**" + txt + "**" + "  :point_left:" + "\n\n" + contents)

# loop to display `engagement_comment` and `engagement_grade` fields in sidebar
def display_engagement():
    for txt in txts:
       engagement_comment = st.sidebar.radio("Engagement Comment: " + txt, ["Substantial engagement with text - good work.", "Satisfactory engagement with text.", "Little engagement with text - needs improvement."], key = txt)
        engagement_grade = st.sidebar.number_input("Engagement Grade: " + txt)



display_txts()

display_engagement()

if button1:

    df = pd.read_csv("Control2.csv")

    df['engagement_grade'] = df.apply(display_engagement())  # <<<< Here's the crux of my difficulty. How do I write the outputs to be written to csv?

    df

    df.to_csv("Control2.csv", index=False)

    st.write("Grades and comments recorded. This process can be repeated as needed.")

但是,当我点击 button1 写入输出时,我收到以下错误:

DuplicateWidgetID: There are multiple identical st.radio widgets with key='TXTs\feedback_0.txt'. To fix this, please make sure that the key argument is unique for each st.radio you create.

Traceback:
File "C:\Users\danie\Desktop\Python\Streamlit\Experiment_3_6_2.py", line 50, in <module>
    df['engagement_grade'] = df.apply(display_engagement())
File "C:\Users\danie\Desktop\Python\Streamlit\Experiment_3_6_2.py", line 37, in display_engagement
    engagement_comment = st.sidebar.radio("Engagement Comment: " + txt, ["Substantial engagement with text - good work.", "Satisfactory engagement with text

我以为我已经在 display_engagement 函数中设置了单独的键,但似乎有些不对劲。解决此问题或以不同方式构建的任何想法或建议?感谢所有建议和帮助。

我稍微修改了您的代码,但这是一般的解决方案。有一些问题。

问题 1:这使得您的列表中只有一个项目被传递给唯一键(在 streamlit 中打印出 txts,您就会明白我的意思)

float_file_count = ((len(files)) / 3)

问题2:你需要让用户动态生成数据作为一个表单,以便一次性全部传递。

问题三:需要访问streamlit会话状态下的唯一键

问题 4:您需要追加到现有的 DataFrame

下面的代码有效,它应该为您提供完成应用程序的框架。顺便说一句,超级酷的主意!我试图保留你的很多语法 sam

import os
import streamlit as st
import pandas as pd
import glob

st.set_page_config(layout="wide")
st.sidebar.header("Grading Interface")
st.header("Demo - Level 3.6.2 (Prototype)")
st.subheader("In this level...")
txts = glob.glob("TXTs/*.txt")



def display_txts():
    with open(txt, 'r', encoding="utf8") as infile:
        contents = infile.read()
        st.markdown(":point_right:  " + "**" + txt + "**" + "  :point_left:" + "\n\n" + contents)

form = st.sidebar.form(key='grading')
submit_button = form.form_submit_button(label='Submit')


for txt in txts:
    display_txts()
    txt = txt.replace("TXTs\", "").replace(".txt", "").replace("_", "")
    rb = form.radio("Engagement Comment: " + txt, ["Substantial engagement with text - good work.", "Satisfactory engagement with text.", "Little engagement with text - needs improvement."], key = txt)

if submit_button:
    # df = pd.read_csv("Control2.csv")
    df = pd.DataFrame(columns=['data'])
    st.write(st.session_state.feedback0)
    #Find out which items in the session state have feedback in the name
    for item in st.session_state:
        if "feedback" in item:
            df = df.append({'data': st.session_state[item]}, ignore_index=True)

    df.to_csv("Control2.csv", index=False)