问题
I have build a function where I append the returns of 5 portfolios to a dataframe which I want to return to a variable . When I run the commands within the function row by row(kind of debugging) I end upwith the variable 'folioReturn'(which is the one I want my script to return) having the right amount of values (e.x 5). But if I call the function, only the first value of the dataframe is returned. Does anyone know how I can get the whole dataframe ?
def portfolioReturns (securities, quintilesNo, perReturns):
'''
this function receives
1)securities: array with the security names and values ** for the purpose of our work the names
should already be sorted
2)quintilesNo: the number of portfolios we want to create
3)perReturns: an array with the returns that will be used for performance measuremnt
It returns an array with the returns for each portfolio
'''
# we calculate the number of securities per portfolio
stdFolioSize = np.divmod(securities.size, quintilesNo)[0] # we take the floor division
folioReturn = [] # pd.DataFrame()
# we create portfolios with equal number of securities except of the last one where we use all the remaining securities
for k in range(0, quintilesNo, 1): # in folio list we store the name of the securities we must include in each portfolio
if k < (quintilesNo - 1):
folioList = securities.index.get_level_values(1)[k * stdFolioSize : (k + 1) * stdFolioSize]
else: # the last portfolio will also include the remainder securities
folioList = securities.index.get_level_values(1)[k * stdFolioSize : securities.size]
# now that we have the list of the securities to be included in the folio, we use the table
# with the periodical returns to check the performance. The portfolio we construct is equally weighted
# first we drop one index(the first index of the country) and then we store all the periodical returns in one-array
perRetFinalTable = pd.DataFrame(perReturns.reset_index(level = 0, drop = True)).T
# using the list of the bonds we want to include in our portfolio we pick the bond returns and
# we store them in one array. Then we calculate the folio return
folio = perRetFinalTable[folioList]
folioReturn = np.append(folioReturn, folio.sum(axis = 1) * (1 / folio.size))
folioReturn = pd.DataFrame(folioReturn).T
# folioReturn = pd.Series(folioReturn).T
return (folioReturn)
回答1:
return statement must be after the for loop if you want whole list in your case during the first loop only the value is returned. just remove the return from for loop it will work fine.
def portfolioReturns (securities, quintilesNo, perReturns):
'''
this function receives
1)securities: array with the security names and values ** for the purpose of our work the names
should already be sorted
2)quintilesNo: the number of portfolios we want to create
3)perReturns: an array with the returns that will be used for performance measuremnt
It returns an array with the returns for each portfolio
'''
# we calculate the number of securities per portfolio
stdFolioSize = np.divmod(securities.size, quintilesNo)[0] # we take the floor division
folioReturn = [] # pd.DataFrame()
# we create portfolios with equal number of securities except of the last one where we use all the remaining securities
for k in range(0, quintilesNo, 1): # in folio list we store the name of the securities we must include in each portfolio
if k < (quintilesNo - 1):
folioList = securities.index.get_level_values(1)[k * stdFolioSize : (k + 1) * stdFolioSize]
else: # the last portfolio will also include the remainder securities
folioList = securities.index.get_level_values(1)[k * stdFolioSize : securities.size]
# now that we have the list of the securities to be included in the folio, we use the table
# with the periodical returns to check the performance. The portfolio we construct is equally weighted
# first we drop one index(the first index of the country) and then we store all the periodical returns in one-array
perRetFinalTable = pd.DataFrame(perReturns.reset_index(level = 0, drop = True)).T
# using the list of the bonds we want to include in our portfolio we pick the bond returns and
# we store them in one array. Then we calculate the folio return
folio = perRetFinalTable[folioList]
folioReturn = np.append(folioReturn, folio.sum(axis = 1) * (1 / folio.size))
folioReturn = pd.DataFrame(folioReturn).T
# folioReturn = pd.Series(folioReturn).T
return (folioReturn)
回答2:
You're basically exiting the function too early.
Here are two examples to make it simpler to follow along:
def test():
lst = []
for num in range(10):
lst = num
return lst
def test2():
lst = []
for num in range(10):
lst.append(num)
return lst
print(test()) # Output: 0
print(test2()) # Output: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In test
we create a list-variable called lst
, then inside of a for-loop, we overwrite lst
with the current variable num
and then immediately issue a return
statement, which only returns 0
because it's the first entry in the for-loop.
In test2
we do the same thing in the start of the loop, however, instead of overwriting lst
we instead use the method list.append()
which adds the value of num
to the already created list.
After we're then done with the whole for-loop, we then use the return
statement to give back the variable lst
which now contains all the values from 0
to 9
.
EDIT: It seems I failed to address the actual problem in your code. There are two major errors:
You're exiting your for-loop using the
return
statement because it's inside of the for-loop. Fix the indentation, and that should be resolved.Inside of your for-loop, you're overwriting
folioReturn
instead of appending the values calculated inside of the for-loop to it. Replace the variablefolioReturn
inside of the for-loop, and then after you've created theDataFrame
, append that value tofolioReturn
.
来源:https://stackoverflow.com/questions/62153383/python-function-returns-only-the-first-value-instead-of-a-dataframe