Further loop iterations don't work

Hi everyone,

I know there are countless topics about loops, but after seeing about 5 of them, I still could not solve a problem that is hunting me for days, now. (I had the same problem both with For and While loops.)

I have the function below (sorry for its length). It runs flawlessly the 1st time, but on the 2nd time, it assigns itself all inputs’ first options (excepts for common_columns) and gets stuck, unable to have the “Join” button clicked again or any previous option changed.

I tried “time”, manually deleting variables and thought of the placeholders (though I couldn’t figure out how to implement them here, the documentation is kinda vague). Could anyone shed some light? Thanks in advance!

The function:

def joinn():
    global dfs
    global firstdf
    right_table = 1
    right_table_columns = 1
    left_table_columns = 1
    joining_type = 1
    join_maker = 1

    loadedKeys = []
    for key in loaded:
        loadedKeys.append(key)
    lefty, righty = st.columns(2)
    while len(loadedKeys) >= 1:

        if len(loadedKeys) == len(loaded):
            first = lefty.radio("Left:", loadedKeys)
            second = righty.radio("Right:", loadedKeys, key=right_table)
            if first == second:
                st.write("A file cannot be joined to itself.")
                st.stop()
        else:
            lefty.write("the previously joined table is automatically on the left:")
            lefty.write(firstdf.head(3))
            second = righty.radio("Right:", loadedKeys, key=right_table)

        if first in loadedKeys:
            for file in loaded:
                if first == str(file):
                    firstdf = loaded[file]
                    lefty.write(firstdf.head(3))
        else:
            pass
        if second in loadedKeys:
            for file in loaded:
                if second == str(file):
                    seconddf = loaded[file]
                    righty.write(seconddf.head(3))
        common_left = lefty.multiselect("Select common columns (MIND THE ORDER):", (firstdf.columns), key=left_table_columns)
        common_right = righty.multiselect("Select common columns (MIND THE ORDER):", (seconddf.columns), key=right_table_columns)
        TOJ = {"left": "keep the full left and add matching data of the right",
               "right": "keep the full right and add matching data of the left",
               "inner": "keep only matching data from both tables",
               "outer": "keep both full tables"}
        joinType = lefty.radio("Select how you want to join your tables:", [key for key in TOJ], key=joining_type)
        lefty.info(TOJ[joinType])
        righty.image('./join_diagram.jpg')
        if st.button('"Join Us"', key=join_maker):
            firstdf.merge(seconddf, how=joinType, left_on=common_left, right_on=common_right)
            st.dataframe(firstdf)
            right_table += 1
            right_table_columns += 1
            left_table_columns += 1
            joining_type += 1
            join_maker += 1
            loadedKeys.remove(first)
            loadedKeys.remove(second)
            if len(loadedKeys) == 0:
                data = firstdf
                return data
            second = loadedKeys[0]
            del seconddf
            del joinType
            del common_left
            del common_right
        else:
            st.stop()

if len(loaded) >= 2:
    joinn()
else:
    for key,value in loaded:
        data = loaded.value()

Update: it was working flawlessly for the first iteration yesterday. Today, the merge is always happening on the left, regardless of the user choice in joinType. I couldn’t figure out why yet.

Hi @Luis_Magalhaes, welcome to the Streamlit community!

I don’t know the answer to your question specifically, but I would guess that the issue is defining Streamlit widgets inside of a loop. While its valid Python, I suspect that when it gets translated to the JavaScript side, you are either losing the reference somehow (that’s kinda what the key argument does), but you are also defining globals, which can be a dangerous practice in general.

What use case are you solving for here?

Best,
Randy

Hi @randyzwitch! Thanks for the reply and the welcoming!

My app’s user will be able to load multiple files and join them into 1 dataframe, for analysis. That’s the purpose of this function. I’ve used the keys from the beginning, and I havent’ faced any problem in other loops (like when loading multiple excel files one by one - necessary due to the need of specifying each file’s worksheet’s name).

The global is necessary because I need to define “data” as dataframe outside this function, in case the user loads only 1 file. But overall, I’m open to suggestions of better alternatives.

The joinType problem (that suddenly stopped worked) continues to puzzle me and pushes me beyond my zen zone. :angry: :grin: