Python - filtration for 2D list - python

I've created a program that can define maximum, minimum and average temperature of 12 months, but I want to extend it by finding months with the hottest and coldest average temperature. My current code is:
def main():
months = [ ["January", 6,3],
["February", 7,3],
["March", 10,4],
["April", 13,6],
["May", 17,9],
["June", 20,12],
["July", 22,14],
["August", 21,14],
["September",19,12],
["October", 14,9],
["November", 10,6],
["December", 7,3] ]
for month in months:
month_name = month[0]
temp = month[1:]
minTemp = min(temp)
avgTemp = sum(temp)/len(temp)
maxTemp = max(temp)
print (month_name, minTemp, avgTemp, maxTemp)
main()
I want to add something like "if month_name have the maximum avg temperature, print month_name and its temperatures. Also if month_name have the minimum avg temperature, print month_name and its temperatures

import math
def main():
months = [ ["January", 6,3],
["February", 7,3],
["March", 10,4],
["April", 13,6],
["May", 17,9],
["June", 20,12],
["July", 22,14],
["August", 21,14],
["September",19,12],
["October", 14,9],
["November", 10,6],
["December", 7,3] ]
mn,mx=math.inf, -math.inf
mx_month=["",0]
mn_month=["",0]
for month in months:
month_name = month[0]
temp = month[1:]
minTemp = min(temp)
avgTemp = sum(temp)/len(temp)
maxTemp = max(temp)
if avgTemp<mn:
mn_month[0],mn_month[1]=month_name,avgTemp
mn=avgTemp
if avgTemp>mx:
mx_month[0],mx_month[1]=month_name,avgTemp
mx=avgTemp
print (month_name, minTemp, avgTemp, avgTemp)
print("Min avg temo month and temp: ",mn_month)
print("Max avg temo month and temp: ",mx_month)
main()

Append the avg to each month and find min/max
months = [["January", 6, 3],
["February", 7, 3],
["March", 10, 4],
["April", 13, 6],
["May", 17, 9],
["June", 20, 12],
["July", 22, 14],
["August", 21, 14],
["September", 19, 12],
["October", 14, 9],
["November", 10, 6],
["December", 7, 3]]
for m in months:
m.append((m[1] + m[2]) / 2)
_min_avg = min(months, key = lambda k: k[3])
_max_avg = max(months, key = lambda k: k[3])
print(_min_avg)
print(_max_avg)

Related

ISO Calendar week number

I am trying to generate week number for 12 weeks from today like weekly wise and i am seeing last 53 week is missing ..
ISO calendar week 2022-Jan-1 is giving week number 52
from datetime import datetime
current_dateTime = datetime.now()
temp_n=12
def week_num_gen():
num=0
global wknum_gen
wknum_gen=[]
for i in range(0,temp_n):
if i==0 :
# Weeknum7 = date.today() + timedelta(days=2)
Weeknum7=datetime(current_dateTime.year, 1,1)
# if i==0 and current_dateTime.year==2023:
# # Weeknum7 = date.today() + timedelta(days=2)
else:
Weeknum7 = Weeknum7 + timedelta(days=7)
wknum_gen.append(Weeknum7.isocalendar().week)
num=num+7
week_num_gen()
wklist_1=list(wknum_gen)
wklist_1
result is below
[52, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
expected is result is below
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,12]
and if i try to generate it from today for 12 weeks
Weeknum7=datetime(current_dateTime.year, 11,2)
result is below with error
[44, 45, 46, 47, 48, 49, 50, 51, 52, 1, 2, 3]
next 12 weeks
expected result is [ 45, 46, 47, 48, 49, 50, 51, 52, 53,1, 2,3]

How to get this output "Output- Mon-Wed-7-19 Thu-11-19 Friday -Sat open 24 hours Sun-closed" from this input

Input 1: opening hrs = [7 , 7, 7, 11, 15, 10, 17]
closing hrs = [19, 19, 19, 19, 15, 10, 7] given this input. I have tried couple ways one such is below. Even this solution is not correct.
Solution which I have tried from my end,
opening_hrs = [7 , 7, 7, 11, 15, 17, 17]
closing_hrs = [19, 19, 19, 19, 15, 7, 7]
days = ['Mon', 'Tue', 'W', 'Th', 'Fr', 'Sa', 'Su']
tmp = [timings[0]]
out = days[0]
for every in range(len(timings)):
if timings[every] not in tmp:
out += '-' + days[every-1]
out += str(timings[every-1]) + '\n'
if every != len(timings) -1:
tmp.append(timings[every])
else:
if timings[-1] not in tmp:
out += '-' + days[-1]
out += str(timings[-1]) + '\n'
tmp.append(timings[-1])
print(out)
I was able to map things and return out for all the days like from Monday to Sunday and their corresponding timings, but couldn't return the output such that if the timings are same for the consecutive days then we should combine those days and show the one timing for them like (Mon -Wed -- 7 to 19).
Use zip() to combine day names with opening and closing times.
Then merge consecutive days that have the same hours (starting from the end of the week going backward to allow deleting items from the list within the for loop):
openTime = [7 , 7, 7, 11, 15, 10, 17]
closeTime = [19, 19, 19, 19, 15, 10, 7]
days = ['Monday','Tuesday','Wednesday','Thursday','Friday',
'Saturday','Sunday']
hours = [[d,f"{ot}-{ct}" if ot<ct else "24 hours" if ct==ot else "closed"]
for d,ot,ct in zip(days,openTime,closeTime)]
for i,(day,time) in enumerate(hours[:0:-1]): # backwards through days
if time==hours[5-i][-1]: # same times as previous
hours[5-i][0] += "-" + day.split("-")[-1] # merge into previous
del hours[6-i] # remove merged day entry
print(", ".join(f"{days}:{time}" for days,time in hours))
Monday-Wednesday:7-19, Thursday:11-19, Friday-Saturday:24 hours, Sunday:closed

Create a combination of "relative" and "grouped" chart in Python

I need to create a combination of "relative" and "grouped" chart in plotly.
I figured out how to create stacked and grouped by using this code:
from plotly import graph_objects as go
import plotly
pyplt = plotly.offline.plot
data = {
"Sports_19": [15, 23, 32, 10, 23, 22, 32, 24],
"Casual_19": [4, 12, 11, 14, 15, 12, 22, 14],
"Yoga_19": [4, 8, 18, 6, 12, 11, 10, 4],
"Sports_20": [11, 18, 18, 0, 20, 12, 12, 11],
"Casual_20": [20, 10, 9, 6, 10, 11, 17, 22],
"Yoga_20": [11, 18, 18, 0, 20, 12, 12, 11],
"labels": ["January", "February", "March", "April", "May", 'June', 'July', "August"]
}
fig = go.Figure()
fig.add_trace(go.Bar(name="Sports",x=data["labels"],y=data["Sports_19"],offsetgroup=19,marker_color='lightsalmon',text=data["Sports_19"],textposition='auto'))
fig.add_trace(go.Bar(name="Casual",x=data['labels'],y=data['Casual_19'],offsetgroup=19,base=data['Sports_19'],marker_color='crimson',text=data["Casual_19"],textposition='auto'))
fig.add_trace(go.Bar(name="Yoga",x=data['labels'],y=data['Yoga_19'],marker_color='indianred',text=data["Yoga_19"],textposition='auto',offsetgroup=19,base=[val1 + val2 for val1, val2 in zip(data["Sports_19"], data["Casual_19"])]))
fig.add_trace(go.Bar(name="Sports_20",x=data["labels"],y=data["Sports_20"],offsetgroup=20,marker_color='lightsalmon',showlegend=False,text=data["Sports_20"],textposition='auto'))
fig.add_trace(go.Bar(name="Casual_20",x=data['labels'],y=data['Casual_20'],offsetgroup=20,base=data['Sports_20'],marker_color='crimson',showlegend=False,text=data["Casual_20"],textposition='auto'))
fig.add_trace(go.Bar(name="Yoga_20", x=data['labels'], y=data['Yoga_20'], marker_color='indianred', text=data["Yoga_20"], showlegend=False, textposition='auto', offsetgroup=20, base=[val1 + val2 for val1, val2 in zip(data["Sports_20"], data["Casual_20"])]))
fig.update_layout(title="2019 vs 2020 Sales by Category",yaxis_title="Sales amount in US$")
fig.show()
pyplt(fig, auto_open=True)
Output is this:
Is there is any way i can convert this graph to combination of "relative" and "grouped"? May be not with plotly, but with matplotlib or another tools?
p.s. Here is the example of "relative graph"(but its not grouped):
Probably the most straightforward way is to create two new dataframes df_perc_19 and df_perc_20 to store your data, normalized to relative percentages for each month in each year, rounding off to two digits using .round(2) since a long decimal will cause the default direction of the text to change - feel free to adjust this however you like.
Then access the values in these new dataframes for your traces, and although it's ugly, you can get percentages to display for the text parameter using something like: text=[str(x)+"%" for x in df_perc_19["Casual_19"]]
import pandas as pd
import plotly
from plotly import graph_objects as go
# pyplt = plotly.offline.plot
data = {
"Sports_19": [15, 23, 32, 10, 23, 22, 32, 24],
"Casual_19": [4, 12, 11, 14, 15, 12, 22, 14],
"Yoga_19": [4, 8, 18, 6, 12, 11, 10, 4],
"Sports_20": [11, 18, 18, 0, 20, 12, 12, 11],
"Casual_20": [20, 10, 9, 6, 10, 11, 17, 22],
"Yoga_20": [11, 18, 18, 0, 20, 12, 12, 11],
# "labels": ["January", "February", "March", "April", "May", 'June', 'July', "August"]
}
labels = ["January", "February", "March", "April", "May", 'June', 'July', "August"]
df = pd.DataFrame(data=data,index=labels)
## normalize data for the months of 2019, and the months of 2020
df_perc_19 = df.apply(lambda x: 100*x[["Sports_19","Casual_19","Yoga_19"]] / x[["Sports_19","Casual_19","Yoga_19"]].sum(),axis=1).round(2)
df_perc_20 = df.apply(lambda x: 100*x[["Sports_20","Casual_20","Yoga_20"]] / x[["Sports_20","Casual_20","Yoga_20"]].sum(),axis=1).round(2)
fig = go.Figure()
## traces for 2019
fig.add_trace(go.Bar(name="Sports",x=labels,y=df_perc_19["Sports_19"],offsetgroup=19,marker_color='lightsalmon',text=[str(x)+"%" for x in df_perc_19["Sports_19"]],textposition='auto'))
fig.add_trace(go.Bar(name="Casual",x=labels,y=df_perc_19['Casual_19'],offsetgroup=19,base=df_perc_19['Sports_19'],marker_color='crimson',text=[str(x)+"%" for x in df_perc_19["Casual_19"]],textposition='auto'))
fig.add_trace(go.Bar(name="Yoga",x=labels,y=df_perc_19['Yoga_19'],marker_color='indianred',text=[str(x)+"%" for x in df_perc_19["Yoga_19"]],textposition='auto',offsetgroup=19,base=[val1 + val2 for val1, val2 in zip(df_perc_19["Sports_19"], df_perc_19["Casual_19"])]))
## traces for 2020
fig.add_trace(go.Bar(name="Sports_20",x=labels,y=df_perc_20["Sports_20"],offsetgroup=20,marker_color='lightsalmon',showlegend=False,text=[str(x)+"%" for x in df_perc_20["Sports_20"]] ,textposition='auto'))
fig.add_trace(go.Bar(name="Casual_20",x=labels,y=df_perc_20['Casual_20'],offsetgroup=20,base=df_perc_20['Sports_20'],marker_color='crimson',showlegend=False,text=[str(x)+"%" for x in df_perc_20["Casual_20"]],textposition='auto'))
fig.add_trace(go.Bar(name="Yoga_20", x=labels, y=df_perc_20['Yoga_20'], marker_color='indianred', text=[str(x)+"%" for x in df_perc_20["Yoga_20"]], showlegend=False, textposition='auto', offsetgroup=20, base=[val1 + val2 for val1, val2 in zip(df_perc_20["Sports_20"], df_perc_20["Casual_20"])]))
fig.update_layout(title="2019 vs 2020 Sales by Category",yaxis_title="Sales amount in US$ (percentage)")
fig.show()
# pyplt(fig, auto_open=True)

Generate random list of timestamps within multiple time intervals in python

Is there any efficient way to generate a list of N random timeframes which do not intersect each other given the initial lower and upper bounds as well as the time intervals that these time periods should have. For example in the following case I want 10 timestamps between 09:00-17:00:
Initial start time: {datetime} YYYY-MM-DD 09:00:00
Initial end time: {datetime} YYYY-MM-DD 17:00:00
Timestamp intervals (in minutes): [32 24 4 20 40 8 27 18 3 4]
where the first time period 32 minutes long, the next 24 and so on.
The way I am doing it at the moment is by using more or less the following code snippet:
def random_time(start, end, timeframe=None):
sec_diff = int((end - start).total_seconds())
secs_to_add = random.randint(0, sec_diff)
return start + timedelta(seconds=secs_to_add)
def in_datetimes_range(self, x, starts, ends):
return np.any((starts <= x) & (x <= ends))
n = 10
dadate = datetime.now()
year = self.dadate.year
month = self.dadate.month
day = self.dadate.day
start = datetime(year, month, day, 9, 0, 0)
end = datetime(year, month, day, 17, 0, 0)
timeframe = [32 24 4 20 40 8 27 18 3 4]
startTimes = []
endTimes = []
for i in range(0, n):
while True:
startTime = random_time(start, end)
endTime = startTime + timedelta(minutes=int(timeframe[i]))
if startTimes:
startTimesAsNpArray = np.array(startTimes)
endTimesAsNpArray = np.array(endTimes)
#check if new time period falls inside existing timeframes or if existing timeframes fall within new time period
inner_bound = np.logical_or(in_datetimes_range(startTime, startTimesAsNpArray, endTimesAsNpArray), in_datetimes_range(endTime, startTimesAsNpArray, endTimesAsNpArray))
outer_bound = np.logical_or(in_datetimes_range(startTimesAsNpArray, startTime, endTime), in_datetimes_range(endTimesAsNpArray, startTime, endTime))
if not inner_bound and not outer_bound:
startTimes.append(startTime)
endTimes.append(endTime)
break
but this is really inefficient and I was looking for something more reliable if possible.
Here is a way to do it: the idea is that if we remove the total duration of the periods from the time available, generate start times in the period that is left, and then postpone them with the cumulated periods before them, we are sure that the intervals won't overlap.
from datetime import datetime, timedelta
import random
def generate_periods(start, end, durations):
durations = [timedelta(minutes=m) for m in durations]
total_duration = sum(durations, timedelta())
nb_periods = len(durations)
open_duration = (end - start) - total_duration
delays = sorted(timedelta(seconds=s)
for s in random.sample(range(0, int(open_duration.total_seconds())), nb_periods))
periods = []
periods_before = timedelta()
for delay, duration in zip(delays, durations):
periods.append((start + delay + periods_before,
start + delay + periods_before + duration))
periods_before += duration
return periods
Sample run:
durations = [32, 24, 4, 20, 40, 8, 27, 18, 3, 4]
start_time = datetime(2019, 9, 2, 9, 0, 0)
end_time = datetime(2019, 9, 2, 17, 0, 0)
generate_periods(start_time, end_time, durations)
# [(datetime.datetime(2019, 9, 2, 9, 16, 1),
# datetime.datetime(2019, 9, 2, 9, 48, 1)),
# (datetime.datetime(2019, 9, 2, 9, 58, 57),
# datetime.datetime(2019, 9, 2, 10, 22, 57)),
# (datetime.datetime(2019, 9, 2, 10, 56, 41),
# datetime.datetime(2019, 9, 2, 11, 0, 41)),
# (datetime.datetime(2019, 9, 2, 11, 2, 37),
# datetime.datetime(2019, 9, 2, 11, 22, 37)),
# (datetime.datetime(2019, 9, 2, 11, 48, 17),
# datetime.datetime(2019, 9, 2, 12, 28, 17)),
# (datetime.datetime(2019, 9, 2, 13, 4, 28),
# datetime.datetime(2019, 9, 2, 13, 12, 28)),
# (datetime.datetime(2019, 9, 2, 15, 13, 3),
# datetime.datetime(2019, 9, 2, 15, 40, 3)),
# (datetime.datetime(2019, 9, 2, 16, 6, 44),
# datetime.datetime(2019, 9, 2, 16, 24, 44)),
# (datetime.datetime(2019, 9, 2, 16, 37, 42),
# datetime.datetime(2019, 9, 2, 16, 40, 42)),
# (datetime.datetime(2019, 9, 2, 16, 42, 50),
# datetime.datetime(2019, 9, 2, 16, 46, 50))]
Like this?
import pandas as pd
from datetime import datetime
date = datetime.now()
start = datetime(date.year, date.month, date.day, 9, 0, 0)
end = datetime(date.year, date.month, date.day, 17, 0, 0)
interval = 32
periods = (end-start).seconds/60/interval
times = pd.date_range(start.strftime("%m/%d/%Y, %H:%M:%S"), periods=periods, freq=str(interval)+'min')
or like this
# =============================================================================
# or if you want the results as a dataframe
# =============================================================================
def xyz(interval):
date = datetime.now()
start = datetime(date.year, date.month, date.day, 9, 0, 0)
end = datetime(date.year, date.month, date.day, 17, 0, 0)
periods = (end-start).seconds/60/interval
return pd.date_range(start.strftime("%m/%d/%Y, %H:%M:%S"), periods=periods, freq=str(interval)+'min')
timeframes = [32,24,4,20,40,8,27,18,3,4]
df_output=pd.DataFrame(index=timeframes, data=[xyz(x) for x in timeframes])

Find max values in a dict containing lists

The dict got the keys years and for each year it's a list of all the temperatures in all 12 months of that year. My goal is to print out a table starting with what year it is and then a new line for each month and the temp that month.
The main thing is to mark the highest temp of all years with (ATH) and mark the highest temp in each year with (YearHighest).
My current code:
temp_dict= {
"2010": [2, 3, 4, 5, 7, 3, 20, 29, 34, 2, 10, 1],
"2011": [2, 7, 4, 5, 9, 3, 20, 9, 34, 2, 10, 10]
}
for key in temp_dict:
print("Year",key,":")
x=0
for temps in temp_dict[key]:
x=x+1
print("Month "+str(x)+":%3d"%temps)
print()
I'm not sure how to make the max function, I was thinking something like this but I can't get it to work:
for key in temp_dict:
ATH = temp_dict[key]
YearHigh = temp_dict[key][0]
for temps in temp_dict[key]:
if temps >= temp_dict[key][0]:
YearHigh = temps
if YearHigh >= ATH:
ATH = YearHigh
How I want my output to look like:
Year 2011 :
Month1: 2
Month2: 7
Month3: 4
Month4: 5
Month5: 9
Month6: 3
Month7: 20
Month8: 9
Month9: 34 (YearHighest)(ATH)
Month10: 2
Month11: 10
Month12: 10
Year 2010 :
Month1: 2
Month2: 3
Month3: 4
Month4: 5
Month5: 7
Month6: 3
Month7: 20
Month8: 29
Month9: 34 (YearHighest)(ATH)
Month10: 2
Month11: 10
Month12: 1
Python has built-in function max, it's considered a good practice to use it.
Max in year:
max(temp_dict["2010"])
Max all time:
max(sum(temp_dict.values(), []))
sum(lists, []) does list flattening, equivalent to
[] + lists[0] + lists[1]...
Python has a builtin function max you can utilize:
for key in temp_dict:
print("Year", key,":")
temps = temp_dict[key]
max_temp = max(temps)
max_index = temps.index(max_temp)
for index, temps in enumerate(temps):
r = "Month "+str(index+1)+":%3d"%temps
if index == max_index:
r += "(YearHighest)(ATH)"
print(r)
You can try something like this:
temp_dict= {
"2010": [2, 3, 4, 5, 7, 3, 20, 29, 34, 2, 10, 1],
"2011": [2, 7, 4, 5, 9, 3, 20, 9, 34, 2, 10, 10]
}
# defines the max of all years with a list comprehension
global_max_temp = max([ max(year_temps) for year_temps in temp_dict.values() ])
# iterates through each year
for year, temps in temp_dict.items():
print("Year {}".format(year))
for i, temp in enumerate(temps):
# prepares the output
temp_string = ["Month{}: {}".format(i+1, temp)]
# builds a list of flags to be displayed
flags = []
if temp == max(temps):
# max in year flag
flags.append("YearHighest")
if temp == global_max_temp:
# absolute max flag
flags.append("ATH")
# joins temp_string and flags in a single line and prints it
print(" ".join(temp_string + [ "({})".format(flag) for flag in flags ]))
Useful links from Python's documentation: enumerate, list comprehensions, max
This is my code.
temp_dict= {
"2010": [2, 3, 4, 5, 7, 3, 20, 29, 34, 2, 10, 1],
"2011": [2, 7, 4, 5, 9, 3, 20, 9, 34, 2, 10, 10]
}
# Find the highest temp of all years
ath = max([ max(v) for v in temp_dict.values()])
for key in temp_dict:
# Output Year
print("Year{k}:".format(k=key))
x=0
# Find max
max_value = max(temp_dict[key])
for temps in temp_dict[key]:
# Output Month
x=x+1
s = "Month {x}:{v:3d}".format(x=str(x), v=temps)
# Tag the max value
if max_value == temps:
s += "(YearHighest)"
if ath == temps:
s += "(ATH)"
print(s)
print()
And this is my output.
Year2010:
Month 1: 2
Month 2: 3
Month 3: 4
Month 4: 5
Month 5: 7
Month 6: 3
Month 7: 20
Month 8: 29
Month 9: 34(YearHighest)(ATH)
Month 10: 2
Month 11: 10
Month 12: 1
Year2011:
Month 1: 2
Month 2: 7
Month 3: 4
Month 4: 5
Month 5: 9
Month 6: 3
Month 7: 20
Month 8: 9
Month 9: 34(YearHighest)(ATH)
Month 10: 2
Month 11: 10
Month 12: 10
Here needs to use max function. It can max value from numbers of a list fast.

Categories

Resources