Search code examples
python-3.xpandasenumerate

Enumerate returns index -1 resulting in ValueError: Length of values does not match length of index


I am trying to make a new column in my df which will be something like:

df["Signal"] = signalList

However, I get this error "Enumerate returns index -1 resulting in ValueError: Length of values does not match length of index". So I checked the len of my column:

print(len(df["Crossover"]))

This returns 8192. So I adjusted the code to print *x so I can see where it goes up to and I get *8191. How can I fix this? Cheers.

signalList = []
 for x,i in enumerate(df["Crossover"]):
print("*"+str(x))
if i == True:
    if df['EMA ' + str(emaShort)].iloc[x] > df['EMA ' + str(emaLong)].iloc[x]:
        signal = "Buy"
        signalList.append(signal)
    elif df['EMA ' + str(emaShort)].iloc[x] < df['EMA ' + str(emaLong)].iloc[x]:
        signal = "Sell"
        signalList.append(signal)
elif i != True:
    signal = "None"
    signalList.append(signal)

EDIT **************************************************************************** I was wondering if you could tell me if it is possible to adjust my code below to take advantage of vectorized processing. As it is so much quicker. The first bit of code is my attempt and it kinda works and the loop below is how I want it to work exactly. The problem I am having is essentially I need the lines before the first buy/sell signal to be None in the "Position Column" However, I can't get the vectorized table to do that. Although it will accurately identify when to switch to long/short anything prior to the signal will be "Short" because the condition returns False. I've not had any luck getting round this.

df["Position"] = np.where(df['Signal'].ne("None"),np.where(df[f'Signal'].eq("Buy"), "Long", "Short"), np.where(df["Position"].shift(1).eq(True), "Long", np.where(df["Position"].shift(1).eq(False), "Short", "None")))

for x,i in enumerate(df['Signal']):
    if i == "Buy":
        df.iloc[x, df.columns.get_loc('Position')] = "Long"
    elif i == "Sell":
            df.iloc[x, df.columns.get_loc('Position')] = "Short"
    else:
        if df["Position"].iloc[x-1] == "Long":
            df.iloc[x, df.columns.get_loc('Position')] = "Long"
        elif df["Position"].iloc[x-1] == "Short":
            df.iloc[x, df.columns.get_loc('Position')] = "Short"
        else:
            df.iloc[x, df.columns.get_loc('Position')] = "None"

Solution

  • First, you probably don't have correct indentation in your code, the correct one is

    signalList = []
    for x, i in enumerate(df["Crossover"]):
        print("*" + str(x))
        if i == True:
            if df['EMA ' + str(emaShort)].iloc[x] > df['EMA ' + str(emaLong)].iloc[x]:
                signal = "Buy"
                signalList.append(signal)
            elif df['EMA ' + str(emaShort)].iloc[x] < df['EMA ' + str(emaLong)].iloc[x]:
                signal = "Sell"
                signalList.append(signal)
        elif i != True:
            signal = "None"
            signalList.append(signal)
    

    Second, the inner if-elif is without else; what about the case if

    df['EMA ' + str(emaShort)].iloc[x] == df['EMA ' + str(emaLong)].iloc[x]:
    

    I suppose there is a row in your df which satisfies just this condition.