Camilla
Camilla

Reputation: 131

ValueError: too many values to unpack (expected 2): pandas

I am new to using pandas dataframe, I would appreciate any help. I have a set of dates and cashflows for different loans, loan set with 120 period is followed by another loan set with 120 periods in csv file. in total there are 10 loans with 120 periods and 120 cash flows for each loan. I am trying to apply xnpv function to calculate npv for each loan's cashflows. But Python shows an error

ValueError: too many values to unpack (expected 2).

I can't understand what I am doing wrong.

Here is my code:

import pandas as pd
from scipy import optimize
def secant_method(tol, f, x0):
    x1 = x0*1.1
    while (abs(x1-x0)/abs(x1) > tol):
        x0, x1 = x1, x1-f(x1)*(x1-x0)/(f(x1)-f(x0))
    return x1
  
def xnpv(rate,cashflows):
    chron_order = sorted(cashflows, key = lambda x: x[0])
    t0 = chron_order[0][0] 
    return sum([cf/(1+rate)**((t-t0).days/365.0) for (t,cf) in chron_order])

s=pd.Series(list(zip(df['date'], df['Total CF'])), index =df.index)
df1=s.groupby(df['loan_number']).apply(list).reset_index(name='cashflows')
cashflows=df1['cashflows']
cashflows

0     [(7/15/2021, 0.152497472), (8/15/2021, 0.23157...
1     [(7/15/2021, -1.731640118), (8/15/2021, -1.272...
2     [(7/15/2021, 0.016080295), (8/15/2021, 0.02423...
3     [(7/15/2021, 0.0), (8/15/2021, 0.0), (9/15/202...
4     [(7/15/2021, -3.481797138), (8/15/2021, -2.792...
5     [(7/15/2021, 0.033370756), (8/15/2021, 0.04979...
6     [(7/15/2021, -2.439990626), (8/15/2021, -2.090...
7     [(7/15/2021, -2.661802291), (8/15/2021, -2.280...
8     [(7/15/2021, 0.0), (8/15/2021, 0.0), (9/15/202...
9     [(7/15/2021, 0.0), (8/15/2021, 0.0), (9/15/202...
10    [(7/15/2021, -1.555758792), (8/15/2021, -1.321...
Name: cashflows, dtype: object

xnpv(0.03, cashflows)

ValueError                                Traceback (most recent call last)
<ipython-input-81-e191dc20193f> in <module>
----> 1 xnpv(0.03, cashflows)

 <ipython-input-35-8666e85828f1> in xnpv(rate, cashflows)
 23     chron_order = sorted(cashflows, key = lambda x: x[0])
 24     t0 = chron_order[0][0] #t0 is the date of the first cash flow
 ---> 25     return sum([cf/(1+rate)**((t-t0).days/365.0) for (t,cf) in 
 chron_order])
 26 
 27 def xirr(cashflows,guess=0.1):

 <ipython-input-35-8666e85828f1> in <listcomp>(.0)
 23     chron_order = sorted(cashflows, key = lambda x: x[0])
 24     t0 = chron_order[0][0] #t0 is the date of the first cash flow
 ---> 25     return sum([cf/(1+rate)**((t-t0).days/365.0) for (t,cf) in 
 chron_order])
 26 
 27 def xirr(cashflows,guess=0.1):
 ValueError: too many values to unpack (expected 2)

Upvotes: 1

Views: 141

Answers (1)

Paul P
Paul P

Reputation: 3927

As suggested in one of the comments, the error points at the line containing the sum:

    return sum([cf/(1+rate)**((t-t0).days/365.0) for (t,cf) in chron_order])

In that line, you are iterating chron_order in a way that every element of chron_order is expected to contain a data structure that can be unpacked into two variables: for (t,cf) in chron_order.

In other words, for this to work, each element in chron_order must be a list, a tuple (or something else that Python can automatically unpack) and each of these must contain exactly two items.

Looking at the output that you posted, it seems that cashflows is a column, where each row in that column is a list of 2-tuples and (at least in some cases) there are more than two of those 2-tuples in a row.

That means, if you iterate chron_order (which is derived from cashflows) the way you are trying to do it now, you are actually iterating a list of lists of 2-tuples which is the reason why the interpreter is complaining.

As to the solution what you need to do in order for this to work is change xnpv() to something like this (as I can only guess what the code is supposed to be doing):

def xnpv(rate, cashflows):
    # chron_orders (plural) is a list of lists of 2-tuples
    chron_orders = sorted(cashflows, key=lambda x: x[0])lists
    sums = []
    for chron_order in chron_orders:
        # chron_oder (singular) is a list of 2-tuples now
        t0 = chron_order[0][0]  
        sums.append(sum([cf/(1+rate)**((t-t0).days/365.0) for (t,cf) in chron_order])

    return sum(sums)  # Just guessing here

Upvotes: 1

Related Questions