how to put a $ in front of my value table numbers - python

I'm new to python and wondering how I can put a dollar sign in this spot? i think it might have something to do with line 31 in my code but I cannot figure it out
https://i.stack.imgur.com/Flv4W.png
here is the code:
#constants
CITY_CLOSE_RATE = 2
CITY_DIST_RATE = 1
BNDRY_DIST = 20
#inputs
propValue = float(input('What is the cost of the property right now?'))
numYears = int(input('Value after how many years?'))
propDist = float(input('How far is the property from your city?'))
# select the right rate depending on the distance to the city
if propDist <= BNDRY_DIST:
rate = CITY_CLOSE_RATE
else:
rate = CITY_DIST_RATE
#calculate percantage
rate = rate / 100
#print header of the table
print(f'{"Years":>5} {"value":>15}')
# calculating property for every year. body of the table
for count in range (1, numYears +1) :
increment = propValue * rate
endVal = propValue + increment
print (f'{count:>5} {endVal :>15.2f}')
propValue= endVal
#print final prop value after appreciation
print(f'Value of the property after {count} years: ${propValue : .2f}')

One way might be to use an earlier f-string to make endVal in to a string with a $ added before. As such the for loop becomes;
for count in range (1, numYears +1):
increment = propValue * rate
endVal = propValue + increment
strEndVal = '$ ' + f'{endVal:,.2f}'
print (f'{count:>5} {strEndVal :>15}')
propValue= endVal

Related

inf answer when using while loops in python to calculate balances

I have to write a program that calculates Balkcom's and Brissie's balances using while-loop and then print the first year where Balkcom's balance surpasses Brissie's
The problem is that when I run the program it gives me inf as the answers for both balances, is there a way to fix this or is there another way to do it using while-loops?
Important info:
Balkcom initial deposit: 1
Brissie initial deposit: 100000
Balkcom interest rate: 5%
Brissie interest rate: 4%
#Define constant & variables
BALKCOM_INI_DEPOSIT = 1
BALKCOM_INT_RATE = 1.05
BRISSIE_INI_DEPOSIT = 100000
BRISSIE_INT_RATE = 104000
balkcom_balance = BALKCOM_INI_DEPOSIT * BALKCOM_INT_RATE
brissie_balance = BRISSIE_INI_DEPOSIT * BRISSIE_INT_RATE
year = 0
sys.set_int_max_str_digits(100000)
while balkcom_balance < brissie_balance:
balkcom_balance = balkcom_balance * BALKCOM_INT_RATE
brissie_balance = brissie_balance * BRISSIE_INT_RATE
year = year + 1
print("Year:", year, " " + "Balkcom balance:", balkcom_balance, "Brissie balance:", brissie_balance)

Issue with Nested If/While/If statement

As a D&D aficionado, I have written out a script to perform any attack and damage rolls for any specified die, including what happens in the event of a critical attack roll (20).
from random import randint
atk_roll = 20
hit_mod = 6
atk_hit = atk_roll + hit_mod
die = 'd10'
dmg_mod = 4
rolls = 1
def dice_roller(x, y, z):
y1 = int(y.strip('d'))
dict = {}
results = []
step = 1
while step <= z:
die = randint(1,y1)
results.append(die)
step += 1
if atk_roll == 20:
total = (sum(results)+dmg_mod) + (y1*z)
pct_dmg = total / (((y1*z)+dmg_mod) + (y1*z))
else:
total = sum(results) + dmg_mod
pct_dmg = total / ((y1*z)+dmg_mod)
dict.update({'Attack Roll: ' + f'{atk_roll} + {hit_mod} = {x}':
{'Damage Roll: ' + f'{z}' + y:
{'Rolls': results, 'Total Damage': total, 'Pct_Damage': f'{pct_dmg:.0%}'}}})
print(dict)
print(dice_roller(atk_hit, die, rolls))
{'Attack Roll: 20 + 6 = 26': {'Damage Roll: 1d10': {'Rolls': [4], 'Total Damage': 18, 'Pct_Damage': '75%'}}}
None
The issue becomes when I introduce a new "if/else" statement to account for a missed attack. The only roll that does not work is a critical roll:
from random import randint
atk_roll = 20
hit_mod = 6
atk_hit = atk_roll + hit_mod
die = 'd10'
dmg_mod = 4
rolls = 1
ac = 15
def dice_roller(x, y, z):
y1 = int(y.strip('d'))
dict = {}
results = []
step = 1
if x >= ac:
while step <= z:
die = randint(1,y1)
results.append(die)
step += 1
if atk_roll == 20:
total = (sum(results)+dmg_mod) + (y1*z)
pct_dmg = total / (((y1*z)+dmg_mod) + (y1*z))
else:
total = sum(results) + dmg_mod
pct_dmg = total / ((y1*z)+dmg_mod)
dict.update({'Attack Roll: ' + f'{atk_roll} + {hit_mod} = {x}':
{'Damage Roll: ' + f'{z}' + y:
{'Rolls': results, 'Total Damage': total, 'Pct_Damage': f'{pct_dmg:.0%}'}}})
print(dict)
else:
print('Your attack missed')
print(dice_roller((atk_hit), die, rolls))
{}
None
When I change the value of "atk_roll" in the second script back to "randint(1,20)", the code works exactly as intended, noting when an attack misses or returning the dictionary of values if the attack hits. I cannot for the life of me figure out why the code is returning a blank dict only when "atk_roll" = 20. Does it have something to do with the nesting syntax of if/while/if? Thanks!
In the second code snippet you provided: the if-else block if ask_roll == 20:
will always be taken and therefore your dictionary will not be populated with values as the atk_roll value is always 20. This is because your dict is being populated in the following else.
This differs from your first piece of code as dict is updated every time the function is called as its located outside of any conditional statements.
I would need more details about what your code does to provide a detailed solution but I will attempt to give a high-level solution. If you are trying to update the dictionary regardless if your atk_roll is equal to 20 then the update should be outside the nested else block in your conditional statement checking if atk_roll is equal to 20. This code snippet is included below.
if atk_roll == 20:
total = (sum(results)+dmg_mod) + (y1*z)
pct_dmg = total / (((y1*z)+dmg_mod) + (y1*z))
else:
total = sum(results) + dmg_mod
pct_dmg = total / ((y1*z)+dmg_mod)
dict.update({'Attack Roll: ' + f'{atk_roll} + {hit_mod} = {x}':
{'Damage Roll: ' + f'{z}' + y:
{'Rolls': results, 'Total Damage': total, 'Pct_Damage': f'{pct_dmg:.0%}'}}})

It is not working as expected. How can i fix this code?

I want the code to increase my semi_annual_income every six months, by making the the semi_annual income increase every six months with by specific percentage. so it was suppose to be according to my math 1000(1.2)^i/6 this equation would increase my income by 0.2 every 6 months where the i is divisible by 6.
I tried to both the expressions when I use the expression 1000(1.2)^i/6 it will give me a very huge number. and the expression 1000(1 +0.2) is giving me the exact answer that 1000(1 + 0.2) should have given me.
number_of_months = 0
total_cost = 100000
semi_annual_income = 1000
starting_salary = 10
semi_annual_rise = 0.2
while semi_annual_income < total_cost:
for i in range(100):
if float(i)%6 == 0:
power_number = float(i)/6
# i am using this to make it increase the semi_annual income just only every six months
semi_annual_income = semi_annual_income *(float(1) + float(semi_annual_rise))
print(power_number)
print(semi_annual_income)
#semi_annual_income = (semi_annual_income *(float(1) + float(semi_annual_rise))** float(power_number))
#The above written code is giving me a very huge number i want it to give me the answer as 1000(1 + 0.2)^i/6
break
I got the answer I wanted from the code but I don't understand why is it giving me the answer without the power and the one with the power is not giving me the answer.
number_of_months = 0
total_cost = 100000
semi_annual_income = 1000
starting_salary = 1000
semi_annual_rise = 0.2
number_of_months = 0
while semi_annual_income < total_cost:
for i in range(1,100):
if float(i)%6 == 0:
power_number = float(i)/6# i am using this to make it increase the
semi_annual income just only every six months
number_of_months = number_of_months + 1
semi_annual_income = starting_salary *(float(1) +
float(semi_annual_rise))**(power_number)
print(power_number)
print(semi_annual_income)
print(number_of_months)
# I think my mistake was the i used semi_annual-income instead of starting salary, this code works as i wanted it to be.
break

Calculating monthly growth percentage from cumulative total growth

I am trying to calculate a constant for month-to-month growth rate from an annual growth rate (goal) in Python.
My question has arithmetic similarities to this question, but was not completely answered.
For example, if total annual sales for 2018 are $5,600,000.00 and I have an expected 30% increase for the next year, I would expect total annual sales for 2019 to be $7,280,000.00.
BV_2018 = 5600000.00
Annual_GR = 0.3
EV_2019 = (BV * 0.3) + BV
I am using the last month of 2018 to forecast the first month of 2019
Last_Month_2018 = 522000.00
Month_01_2019 = (Last_Month_2018 * CONSTANT) + Last_Month_2018
For the second month of 2019 I would use
Month_02_2019 = (Month_01_2019 * CONSTANT) + Month_01_2019
...and so on and so forth
The cumulative sum of Month_01_2019 through Month_12_2019 needs to be equal to EV_2019.
Does anyone know how to go about calculating the constant in Python? I am familiar with the np.cumsum function, so that part is not an issue. My problem is I cannot solve for the constant I need.
Thank you in advance and please do not hesitate to ask for further clarification.
More clarification:
# get beginning value (BV)
BV = 522000.00
# get desired end value (EV)
EV = 7280000.00
We are trying to get from BV to EV (which is a cumulative sum) by calculating the cumulative sum of the [12] monthly totals. Each monthly total will have a % increase from the previous month that is constant across months. It is this % increase that I want to solve for.
Keep in mind, BV is the last month of the previous year. It is from BV that our forecast (i.e., Months 1 through 12) will be calculated. So, I'm thinking that it makes sense to go from BV to the EV plus the BV. Then, just remove BV and its value from the list, giving us EV as the cumulative total of Months 1 through 12.
I imagine using this constant in a function like this:
def supplier_forecast_calculator(sales_at_cost_prior_year, sales_at_cost_prior_month, year_pct_growth_expected):
"""
Calculates monthly supplier forecast
Example:
monthly_forecast = supplier_forecast_calculator(sales_at_cost_prior_year = 5600000,
sales_at_cost_prior_month = 522000,
year_pct_growth_expected = 0.30)
monthly_forecast.all_metrics
"""
# get monthly growth rate
monthly_growth_expected = CONSTANT
# get first month sales at cost
month1_sales_at_cost = (sales_at_cost_prior_month*monthly_growth_expected)+sales_at_cost_prior_month
# instantiate lists
month_list = ['Month 1'] # for months
sales_at_cost_list = [month1_sales_at_cost] # for sales at cost
# start loop
for i in list(range(2,13)):
# Append month to list
month_list.append(str('Month ') + str(i))
# get sales at cost and append to list
month1_sales_at_cost = (month1_sales_at_cost*monthly_growth_expected)+month1_sales_at_cost
# append month1_sales_at_cost to sales at cost list
sales_at_cost_list.append(month1_sales_at_cost)
# add total to the end of month_list
month_list.insert(len(month_list), 'Total')
# add the total to the end of sales_at_cost_list
sales_at_cost_list.insert(len(sales_at_cost_list), np.sum(sales_at_cost_list))
# put the metrics into a df
all_metrics = pd.DataFrame({'Month': month_list,
'Sales at Cost': sales_at_cost_list}).round(2)
# return the df
return all_metrics
Let r = 1 + monthly_rate. Then, the problem we are trying to solve is
r + ... + r**12 = EV/BV. We can use numpy to get the numeric solution. This should be relatively fast in practice. We are solving a polynomial r + ... + r**12 - EV/BV = 0 and recovering monthly rate from r. There will twelve complex roots, but only one real positive one - which is what we want.
import numpy as np
# get beginning value (BV)
BV = 522000.00
# get desired end value (EV)
EV = 7280000.00
def get_monthly(BV, EV):
coefs = np.ones(13)
coefs[-1] -= EV / BV + 1
# there will be a unique positive real root
roots = np.roots(coefs)
return roots[(roots.imag == 0) & (roots.real > 0)][0].real - 1
rate = get_monthly(BV, EV)
print(rate)
# 0.022913299846925694
Some comments:
roots.imag == 0 may be problematic in some cases since roots uses a numeric algorithm. As an alternative, we can pick a root with the least imaginary part (in absolute value) among all roots with a positive real part.
We can use the same method to get rates for other time intervals. For example, for weekly rates, we can replace 13 == 12 + 1 with 52 + 1.
The above polynomial has a solution by radicals, as outlined here.
Update on performance. We could also frame this as a fixed point problem, i.e. to look for a fixed point of a function
x = EV/BV * x ** 13 - EV/BV + 1
The fix point x will be equal to (1 + rate)**13.
The following pure-Python implementation is roughly four times faster than the above numpy version on my machine.
def get_monthly_fix(BV, EV, periods=12):
ratio = EV / BV
r = guess = ratio
while True:
r = ratio * r ** (1 / periods) - ratio + 1
if abs(r - guess) < TOLERANCE:
return r ** (1 / periods) - 1
guess = r
We can make this run even faster with a help of numba.jit.
I am not sure if this works (tell me if it doesn't) but try this.
def get_value(start, end, times, trials=100, _amount=None, _last=-1, _increase=None):
#don't call with _amount, _last, or _increase! Only start, end and times
if _amount is None:
_amount = start / times
if _increase is None:
_increase = start / times
attempt = 1
for n in range(times):
attempt = (attempt * _amount) + attempt
if attempt > end:
if _last != 0:
_increase /= 2
_last = 0
_amount -= _increase
elif attempt < end:
if _last != 1:
_increase /= 2
_last = 1
_amount += _increase
else:
return _amount
if trials <= 0:
return _amount
return get_value(start, end, times, trials=trials-1,
_amount=_amount, _last=_last, _increase=_increase)
Tell me if it works.
Used like this:
get_value(522000.00, 7280000.00, 12)

Conditionally setting values with df.loc inside a loop

I'm querying an MS Access db to retrieve a set of leases. My task is to calculate monthly totals for base rent for the next 60 months. The leases have dates related to start and end in order to calculate the correct periods in the event a lease terminates prior to 60 periods. My current challenge comes in when I attempt to increase the base rent by a certain amount whenever it's time to increment for that specific lease. I'm at a beginner level with Python/pandas so my approach is likely not optimum and the code rough looking. It's likely a vectorized approach is better suited however i'm not quite able to execute such code yet.
Data:
Lease input & output
Code:
try:
sql = 'SELECT * FROM [tbl_Leases]'
#sql = 'SELECT * FROM [Copy Of tbl_Leases]'
df = pd.read_sql(sql, conn)
#print df
#df.to_csv('lease_output.csv', index_label='IndexNo')
df_fcst_periods = pd.DataFrame()
# init increments
periods = 0
i = 0
# create empty lists to store looped info from original df
fcst_months = []
fcst_lease_num = []
fcst_base_rent = []
fcst_method = []
fcst_payment_int = []
fcst_rate_inc_amt = []
fcst_rate_inc_int = []
fcst_rent_start = []
# create array for period deltas, rent interval calc, pmt interval calc
fcst_period_delta = []
fcst_rate_int_bool = []
fcst_pmt_int_bool = []
for row in df.itertuples():
# get min of forecast period or lease ending date
min_period = min(fcst_periods, df.Lease_End_Date[i])
# count periods to loop for future periods in new df_fcst
periods = (min_period.year - currentMonth.year) * 12 + (min_period.month - currentMonth.month)
for period in range(periods):
nextMonth = (currentMonth + monthdelta(period))
period_delta = (nextMonth.year - df.Rent_Start_Date[i].year) * 12 + (nextMonth.month - df.Rent_Start_Date[i].month)
period_delta = float(period_delta)
# period delta values allow us to divide by the payment & rent intervals looking for integers
rate_int_calc = period_delta/df['Rate_Increase_Interval'][i]
pmt_int_calc = period_delta/df['Payment_Interval'][i]
# float.is_integer() method - returns bool
rate_int_bool = rate_int_calc.is_integer()
pmt_int_bool = pmt_int_calc.is_integer()
# conditional logic to handle base rent increases
if df['Forecast_Method'][i] == "Percentage" and rate_int_bool:
rate_increase = df['Base_Rent'][i] * (1 + df['Rate_Increase_Amt'][i]/100)
df.loc[df.index, "Base_Rent"] = rate_increase
fcst_base_rent.append(df['Base_Rent'][i])
print "Both True"
else:
fcst_base_rent.append(df['Base_Rent'][i])
print rate_int_bool
fcst_rate_int_bool.append(rate_int_bool)
fcst_pmt_int_bool.append(pmt_int_bool)
fcst_months.append(nextMonth)
fcst_period_delta.append(period_delta)
fcst_rent_start.append(df['Rent_Start_Date'][i])
fcst_lease_num.append(df['Lease_Number'][i])
#fcst_base_rent.append(df['Base_Rent'][i])
fcst_method.append(df['Forecast_Method'][i])
fcst_payment_int.append(df['Payment_Interval'][i])
fcst_rate_inc_amt.append(df['Rate_Increase_Amt'][i])
fcst_rate_inc_int.append(df['Rate_Increase_Interval'][i])
i += 1
df_fcst_periods['Month'] = fcst_months
df_fcst_periods['Rent_Start_Date'] = fcst_rent_start
df_fcst_periods['Lease_Number'] = fcst_lease_num
df_fcst_periods['Base_Rent'] = fcst_base_rent
df_fcst_periods['Forecast_Method'] = fcst_method
df_fcst_periods['Payment_Interval'] = fcst_payment_int
df_fcst_periods['Rate_Increase_Amt'] = fcst_rate_inc_amt
df_fcst_periods['Rate_Increase_Interval'] = fcst_rate_inc_int
df_fcst_periods['Period_Delta'] = fcst_period_delta
df_fcst_periods['Rate_Increase_Interval_bool'] = fcst_rate_int_bool
df_fcst_periods['Payment_Interval_bool'] = fcst_pmt_int_bool
except Exception, e:
print str(e)
conn.close()
I ended up initializing a variable before the periods loop which allowed me to perform a calculation when looping to obtain the correct base rents for subsequent periods.
# init base rent, rate increase amount, new rate for leases
base_rent = df['Base_Rent'][i]
rate_inc_amt = float(df['Rate_Increase_Amt'][i])
new_rate = 0
for period in range(periods):
nextMonth = (currentMonth + monthdelta(period))
period_delta = (nextMonth.year - df.Rent_Start_Date[i].year) * 12 + (nextMonth.month - df.Rent_Start_Date[i].month)
period_delta = float(period_delta)
# period delta values allow us to divide by the payment & rent intervals looking for integers
rate_int_calc = period_delta/df['Rate_Increase_Interval'][i]
pmt_int_calc = period_delta/df['Payment_Interval'][i]
# float.is_integer() method - returns bool
rate_int_bool = rate_int_calc.is_integer()
pmt_int_bool = pmt_int_calc.is_integer()
# conditional logic to handle base rent increases
if df['Forecast_Method'][i] == "Percentage" and rate_int_bool:
new_rate = base_rent * (1 + rate_inc_amt/100)
base_rent = new_rate
fcst_base_rent.append(new_rate)
elif df['Forecast_Method'][i] == "Manual" and rate_int_bool:
new_rate = base_rent + rate_inc_amt
base_rent = new_rate
fcst_base_rent.append(new_rate)
else:
fcst_base_rent.append(base_rent)
Still open for any alternative approaches though!

Categories