Formula to subtract Month, Week, and Day - excel

I have a list of days, and I am trying to create a formula that will take the days balance and tell me how many months, weeks, and days they are.
example: 28 days = 0 months, 4 weeks, 0 days
it's worth mentioning that months = 31 days, weeks = 7 days, and days are the leftover balance.
here is an example list:
8
30
16
12
12
1
12
6
1
20
6
12
14
3
53
40
19
4
3
2
2
12
14
22
91
6
62
4
17
any help appreciated, thank you

Use:
=INT(A1/31) & " months, " & INT((A1-INT(A1/31)*31)/7) & " weeks, " & A1 - INT(A1/31) * 31 - INT((A1-INT(A1/31)*31)/7) * 7 & " days"

Let me give you an idea, without the actual formula, for the examples 91 and 53:
First you divide by 31:
91 DIV 31 = 2
53 DIV 31 = 1
You subtract that from the original number, and divide by 7:
91 - (2 * 31) = 29, 29 DIV 7 = 4
53 - (1 * 31) = 22, 22 DIV 7 = 3
You subtract that from the remaining number, in order to get the number of remaining days:
27 - (4 * 7) = 1
22 - (3 * 7) = 1
So:
91 : 2 months, 4 weeks and 1 day.
53 : 1 month, 3 weeks and 1 day.

Related

Python calendar with loops

days = int(input("Enter number of days: "))
day_of_week = input("The first day of the week: ")
print("{:>3}{:>3}{:>3}{:>3}{:>3}{:>3}{:>3}".format("S","M","T","W","Th","F","S"))
for d in range(1, days + 1):
print("{:3}".format(d),end="")
if (d % 7 == 0):
print()
Here's my output:
I'm confused... What should I add so that the first day of the week is my input's?
Below is one solution that actually uses the start day that you enter. You'll notice a couple of other improvements as well, specifically:
using an array of days for validation (I've made them match my sensibilities of two characters each but they'll work with the same entries you originally had);
using that same array for figuring out where the month should start;
also using it for simplifying the heading output;
validates the number of days to output;
adds a final newline output; and
uses f-strings for formatting (I prefer this because it localises the value to where it should be, rather than way out to the right somewhere in the format() parameter area, where you have to go searching for it).
The code is:
# Valid day list, adjust as necessary.
day_list = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]
# Get days in month, with validation.
days = -1
while days < 1 or days > 31:
try:
days = int(input("Enter number of days: "))
if days < 28 or days > 31:
days = -1
except ValueError:
days = -1
# Get starting day, with validation.
start_day = ""
while start_day not in day_list:
start_day = input(f"The first day of the week ({', '.join(day_list)}): ")
# Output heading line.
for day in day_list:
print(f"{day:>3}", end="")
print()
# Pad with spaces in first week if needed.
start_pos = day_list.index(start_day)
for _ in range(start_pos):
print(" ", end="")
# Output each day, wrapping to new week if needed.
for day in range(1, days + 1):
if (start_pos != 0 and start_pos % 7 == 0):
print()
print(f"{day:3}", end="")
start_pos += 1
# Output final newline.
print()
A couple of sample runs:
Enter number of days: 27
Enter number of days: 32
Enter number of days: 28
The first day of the week (Su, Mo, Tu, We, Th, Fr, Sa): blah
The first day of the week (Su, Mo, Tu, We, Th, Fr, Sa): Mo
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28
Enter number of days: 30
The first day of the week (Su, Mo, Tu, We, Th, Fr, Sa): Su
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Enter number of days: 29
The first day of the week (Su, Mo, Tu, We, Th, Fr, Sa): Sa
Su Mo Tu We Th Fr Sa
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
days_of_week = ["S","M","T","W","Th","F","St"]
days = int(input("Enter number of days: "))
day_of_week = input("The first day of the week: ")
index = days_of_week.index(day_of_week)
new_days_of_week = days_of_week[index:]+days_of_week[:index]
print("{:>3}{:>3}{:>3}{:>3}{:>3}{:>3}{:>3}".format(*new_days_of_week))
for d in range(1, days + 1):
print("{:3}".format(d),end="")
if (d % 7 == 0):
print()
Output
Enter number of days: 31
The first day of the week: Th
Th F St S M T W
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31

Pandas - Fill N rows for a specific column with a integer value and increment the integer there after

I have a dataframe to which I added say a column named col_1. I want to add integer values to that column starting from the first row that increment after every 4th row. So the new resulting column should have values of as such.
col_1
1
1
1
1
2
2
2
2
The current approach I have is a very brute force one:
for x in range(len(df)):
if x <= 3:
df['col_1'][x] = 1
if x >3 and x <= 7:
df['col_1'][x] = 2
This might work for something small but when moving to something larger it will chew up a lot of time.
If there si default RangeIndex you can use integer division with add 1:
df['col_1'] = df.index // 4 + 1
Or for general solution use helper array by lenght of DataFrame:
df['col_1'] = np.arange(len(df)) // 4 + 1
For repeat 1 and 2 pattern use also modulo by 2 like:
df = pd.DataFrame({'a':range(20, 40)})
df['col_1'] = (np.arange(len(df)) // 4) % 2 + 1
print (df)
a col_1
0 20 1
1 21 1
2 22 1
3 23 1
4 24 2
5 25 2
6 26 2
7 27 2
8 28 1
9 29 1
10 30 1
11 31 1
12 32 2
13 33 2
14 34 2
15 35 2
16 36 1
17 37 1
18 38 1
19 39 1

How to convert multi-indexed datetime index into integer?

I have a multi indexed dataframe(groupby object) as the result of groupby (by 'id' and 'date').
x y
id date
abc 3/1/1994 100 7
9/1/1994 90 8
3/1/1995 80 9
bka 5/1/1993 50 8
7/1/1993 40 9
I'd like to convert those dates into an integer-like, such as
x y
id date
abc day 0 100 7
day 1 90 8
day 2 80 9
bka day 0 50 8
day 1 40 9
I thought it would be simple but I couldn't get there easily. Is there a simple way to work on this?
Try this:
s = 'day ' + df.groupby(level=0).cumcount().astype(str)
df1 = df.set_index([s], append=True).droplevel(1)
x y
id
abc day 0 100 7
day 1 90 8
day 2 80 9
bka day 0 50 8
day 1 40 9
You can calculate the new level and create a new index:
lvl1 = 'day ' + df.groupby('id').cumcount().astype('str')
df.index = pd.MultiIndex.from_tuples((x,y) for x,y in zip(df.index.get_level_values('id'), lvl1) )
output:
x y
abc day 0 100 7
day 1 90 8
day 2 80 9
bka day 0 50 8
day 1 40 9

Simple python program using while loops, off by one error

I have tried to figure out where the off by one error is and have had no luck. I am an absolute beginner at programming. The increase is supposed to start on year two, but my code adds it to year one. Thanks in advance for any and all help!
##
# salaryschedule.py
# 2/15/2017
# This program will calculate and print the salary schedule for years 1
# through 30 for the teachers in Murdock County. For each year of
# experience, up to 20 years, the salary is increased by 2%.
# Each year after 20, the salary stays the same as year 20.
##
RATE = 2.0
INITIAL_SALARY = 37238.00
salary = INITIAL_SALARY
year = 1
print("Murdock County")
print("Teacher Salary Schedule")
print()
print("Year Salary")
print("---- ------")
while year < 31 :
increase = salary * RATE / 100
salary = salary + increase
print("%4d %15.2f" % (year, salary))
year = year + 1
You only have to print the salary before increasing it.
RATE = 2.0
INITIAL_SALARY = 37238.00
salary = INITIAL_SALARY
year = 1
print("Murdock County")
print("Teacher Salary Schedule")
print()
print("Year Salary")
print("---- ------")
while year < 31 :
print("%4d %15.2f" % (year, salary))
increase = salary * RATE / 100
salary = salary + increase
year = year + 1
Output:
Murdock County
Teacher Salary Schedule
Year Salary
---- ------
1 37238.00
2 37982.76
3 38742.42
4 39517.26
5 40307.61
6 41113.76
7 41936.04
8 42774.76
9 43630.25
10 44502.86
11 45392.91
12 46300.77
13 47226.79
14 48171.32
15 49134.75
16 50117.45
17 51119.79
18 52142.19
19 53185.03
20 54248.73
21 55333.71
22 56440.38
23 57569.19
24 58720.57
25 59894.99
26 61092.89
27 62314.74
28 63561.04
29 64832.26
30 66128.90
Your while loop calculates the increase for the year, which is one, and then prints that. But you want to simply print year one as is, correct? So, the simple solution is just moving the print setting to the top of the loop. Year one will be calculated correctly, and then it will change the numbers of the salary and increase before restarting the loop. Like this:
while year < 31 :
print("%4d %15.2f" % (year, salary))
increase = salary * RATE / 100
salary = salary + increase
year = year + 1
Take note, that it will calculate the next salary/increase on the last loop, but not print it. Alternatively, add a print line before the loop that prints year one, such that the loop starts on year 2 (full code for second example):
RATE = 2.0
INITIAL_SALARY = 37238.00
salary = INITIAL_SALARY
year = 1
print("Murdock County")
print("Teacher Salary Schedule")
print()
print("Year Salary")
print("---- ------")
#Changed to so that salary does not increase after 20 years.
print("%4d %15.2f" % (year, salary))
while year < 31 :
if year < 20:
increase = salary * RATE / 100
salary = salary + increase
year = year + 1
print("%4d %15.2f" % (year, salary))
else:
year = year + 1
print("%4d %15.2f" % (year, salary))
Gives the output below, note that salary does is increased on year 20. If you do not want this, change the 20 in the if statement, to 19, so that it stops adding the increase one year earlier:
Murdock County
Teacher Salary Schedule
Year Salary
---- ------
1 37238.00
2 37982.76
3 38742.42
4 39517.26
5 40307.61
6 41113.76
7 41936.04
8 42774.76
9 43630.25
10 44502.86
11 45392.91
12 46300.77
13 47226.79
14 48171.32
15 49134.75
16 50117.45
17 51119.79
18 52142.19
19 53185.03
20 54248.73
21 54248.73
22 54248.73
23 54248.73
24 54248.73
25 54248.73
26 54248.73
27 54248.73
28 54248.73
29 54248.73
30 54248.73
31 54248.73

Binning values in Python3

Say I have the following txt file
Distances Counts
1 5
2 5
3 9
4 10
9 10
10 10
11 5
14 5
20 1
21 1
23 2
I would like a way to bin according to the first column and sum the second column.
The correct output if you use a bin of 5 would be
0-5 29
5-10 20
10-15 10
15-20 20
20-25 3
or just
5 29
10 20
15 10
20 20
25 3
i tried
binfile = open('distances.txt', 'r')
binsize = 5
summar = 0
binsize2 = binsize
for line in binfile:
line = line.strip().split('\t')
distance = int(line[0])
counts = int(line[1])
if distance <= binsize2:
summar += counts
else:
print(str(binsize2)+'\t'+str(summar))
binsize2 = binsize2 + binsize
summar = counts
but it doesn't print the last bin. Any suggestions?

Resources