I did a plot with the bokeh library, the output seems OK except for a overlapping of the x categorical variables.
There is a simple way to separate each month so there is no overlap between each other ?
I tried with dodge() but I couldn't define the parameters inside the function
cumple.txt file:
{"people":
[{"name": "daniela", "birthday": "8/05/1990"},
{"name": "mariano", "birthday": "5/08/1990"},
{"name": "agustin", "birthday": "27/11/1993"},
{"name": "laura", "birthday": "20/10/2000"}]}
Here is my code and the output:
from collections import Counter
import json
from bokeh.plotting import figure, show, output_file
with open("cumple.txt", "r") as f:
info = json.load(f)#carga todo el dictionario en info
s=[]
for i in info['people']:
s.append(i['birthday'])
months=[]
num_to_string = {
1: "January",
2: "February",
3: "March",
4: "April",
5: "May",
6: "June",
7: "July",
8: "August",
9: "September",
10: "October",
11: "November",
12: "December"
}
month=0
for x in s:
month=int(x.split('/')[1])[![enter image description here][1]][1]
months.append(num_to_string[month])
output_file("figura.html")
x_categories = []
for u in num_to_string.values():
x_categories.append(u)
print(x_categories)
x=[]
for j in months:
x.append(j)
print (x)
y=[]
for r in Counter(months).values():
y.append(r)
print(y)
p = figure(title='cumple de amigos',x_range=x_categories, x_axis_label='months', y_axis_label='amount of birthdays')
p.title.align = 'center'
p.vbar(x=x, top=y, width=0.5)
show(p)
print(Counter(months))
Two obvious ways to avoid the labels overlapping:
Increase the width of the graph by setting plot_width:
p = figure(title='cumple de amigos',x_range=x_categories, x_axis_label='months', y_axis_label='amount of birthdays', plot_width=1000)
Rotate the X-axis labels (don't forget to import pi):
p.xaxis.major_label_orientation = pi/4
Related
one of the revision questions was to create a function that checks if a date is valid or not and return a boolean. We were given the first two lines of the function, as so.
Edit: We are not allowed to use inbuilt functions that do all the work such as date.time
month_names = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
days_in_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
Where the days_in_month list contains the maximum day number for the respective months.
Test cases:
is_a_valid_date("January 28 6")) False
is_a_valid_date("January 21")) True
is_a_valid_date(" June 15B ")) False
Code so far:
def is_a_valid_date(date):
month_names = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
days_in_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
clean_date = date.split()
clean_date[1:] = ["".join(clean_date[1:])]
a = False
b = False
if clean_date[0] in month_names:
a = True
x = month_names.find(clean_date[0])
else:
a = a
if clean_date[1].isdigit() == True and int(clean_date[1]) <= int(days_in_month[x]):
b = True
else:
b = b
if a == True and b == True:
return True
else:
return False
I'm having trouble figuring out how to create a condition that sees if the date number inputted is <= the respective month's maximum date number if a = True. I tried using .find but it doesn't seem to work on lists and even then I'm not sure I implemented it properly.
You can simplify that condition like this:
def is_a_valid_date(date):
month_names = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October",
"November", "December"]
days_in_month = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
month, day = date.split(maxsplit=1)
if day.isdigit():
return int(day) <= days_in_month[month_names.index(month)]
return False
Get the name of the month and day from date. Use that name to find days count in days list. Then convert days to int and compare with value from that list. If day can't be converted to int just return False.
I suggest making a dictionary for every max. no. of days per month (eg. days_in_month={January:31,...} and use days_in_month.get(clean_date[0]) instead. so you don't need x also or clean_date[1]
I hope my answer is what you are looking for.
First I have a dictionary that contains all of the months and their max day number values. We check the inputted day value against the inputted month name using the dictionary month_dictionary and get() like this: if day > month_dictionary.get(month):. If the day value is larger than the month's max day value or smaller than 0, than the function returns False and tells you why (which you can delete if you want).
The second function just has a fancy line that makes inputting the date in easier. month, dayRAW = date.split(" ") splits the 1 inputted string into 2 variables, month and dayRAW when the program sees a space in the string. They will then be used in the same way as the first function (after converting the day string into a number, day = int(dayRAW)).
month_dictionary = {"January": 31,
"February": 28,
"March": 31,
"April": 30,
"May": 31,
"June": 30,
"July": 31,
"August": 31,
"September": 30,
"October": 31,
"November": 30,
"December": 31}
def is_a_valid_date_1(month, day):#Input the month with quotes
if day > month_dictionary.get(month):#Finds the corresponding value(number of days) to the month name
print("Day number is too large")
return False
elif day <= 0:
print("Day number can't be zero or smaller")
return False
else:
print("This is a valid date")
return True
def is_a_valid_date_2(date):
month, dayRAW = date.split(" ")#Separates the date string when it sees a space
day = int(dayRAW)#Turns the string into a workable integer
if day > month_dictionary.get(month):#Finds the corresponding value(number of days) to the month name
print("Day number is too large")
return False
elif day <= 0:
print("Day number can't be zero or smaller")
return False
else:
print("This is a valid date")
return True
It also appears mx0 has a condensed version of what I have written. Nice job mate.
I also hope this helps any other passing people :)
So I'm doing a python project and I need to organize a list of values by dictionary. I would like to know if there's a faster way than just doing what I'm doing.
This is what I've done, is there a more efficient and easier way to do this?
def catogorize_by_mortality(hurricanes):
damage_scale = {0: 0, 1: 100, 2: 500, 3: 1000, 4: 1e4}
hurricane_mortality_dict = {0:[], 1:[], 2:[], 3:[], 4:[], 5:[]}
for hurricane in hurricanes:
current_hurricane = hurricanes[hurricane]
death_count = current_hurricane['Deaths']
if death_count > damage_scale[0] and death_count < damage_scale[1]:
hurricane_mortality_dict[0] += hurricane
elif death_count > damage_scale[1] and death_count < damage_scale[2]:
hurricane_mortality_dict[1] += hurricane
elif death_count > damage_scale[2] and death_count < damage_scale[3]:
hurricane_mortality_dict[2] += hurricane
elif death_count > damage_scale[3] and death_count < damage_scale[4]:
hurricane_mortality_dict[3] += hurricane
elif death_count >= damage_scale[4]:
hurricane_mortality_dict[4] += hurricane
else:
hurricane_mortality_dict[5] += hurricane
return hurricane_mortality_dict
# example of the hurricanes dictionary when printed
{'Cuba I': {'Name': 'Cuba I', 'Month': 'October', 'Year': 1924, 'Max Sustained Wind': 165, 'Areas Affected': ['Central America', 'Mexico', 'Cuba', 'Florida', 'The Bahamas'], 'Deaths': 90}
# this is what it returns
deaths.')
{0: ['C', 'u', 'b', 'a'
What's supposed to happen is that it will return the hurricane's names categorized but instead it splits them up into characters what's happening?
hurricane_mortality_dict[i] is defined as a list, near the top of the function:
hurricane_mortality_dict = {0:[], 1:[], 2:[], 3:[], 4:[], 5:[]}
So in your conditional, when you do hurricane_mortality_dict[i] += hurricane, you're trying to add a string and a list, which treats the string as a list of characters - hence your output.
All you need to do is change each:
hurricane_mortality_dict[i] += hurricane
to:
hurricane_mortality_dict[i].append(hurricane)
For your example input this then results in:
{0: ['Cuba I'], 1: [], 2: [], 3: [], 4: [], 5: []}
I am dealing with monthly data for a number of different data sets (e.g. air temperature, ocean temperature, wind speeds etc), whereby each month and each data set will share similar attributes. I want to be able to initialise and populate these attributes as efficiently as possible. So far I can only think of trying to somehow append new attributes to pre-existing attributes. Is this possible in Python?
For example, let's say I initialise all my monthly variables like the following:
class Data_Read:
def __init__(self, monthly=np.zeros((200,200,40))): #3D data
self.jan = monthly
self.feb = monthly
self.march = monthly
self.april = monthly
self.may = monthly
self.june = monthly
self.july = monthly
self.august = monthly
self.sept = monthly
self.oct = monthly
self.nov = monthly
self.dec = monthly
Then I can create a new data set for each month which will become something like air_temp.jan or wind_speed.june by doing the following:
air_temp = Data_Read()
wind_speed = Data_Read()
These would be the raw data attributes. However I would then like to do some processing to each of these data sets (like de-trending). Is there a way I can create a class (or a new class?) that will generate new attributes like self.jan.detrend. Basically I want to avoid having to write 12 lines of code for every attribute I want to create, and then be able to easily call any "attribute of the attribute" in my data processing functions thereafter.
Many thanks.
Here's an example of how you could store everything internally in a dictionary and still reference the arrays as attributes as well as call functions on arrays by name:
import numpy as np
class Data_Read:
def __init__(self, monthly_shape=(200, 200, 40)): #3D data
months = [
"jan",
"feb",
"march",
"april",
"may",
"june",
"july",
"august",
"sept",
"oct",
"nov",
"dec"
]
self._months = {month: np.zeros(monthly_shape) for month in months}
def detrend(self, month):
# this is a dummy function that just increments
return self._months[month] + 1
def __getattr__(self, name):
if name in self._months:
return self._months[name]
return super().__getattr__(name)
air_temp = Data_Read()
print(air_temp.jan.shape) # (200, 200, 40)
print((air_temp.detrend("jan") == 1).all()) # True
You can also achieve the same result using setattr and getattr because attributes are just stored in a dictionary on the object anyway:
import numpy as np
class Data_Read:
def __init__(self, monthly_shape=(200, 200, 40)): #3D data
months = [
"jan",
"feb",
"march",
"april",
"may",
"june",
"july",
"august",
"sept",
"oct",
"nov",
"dec"
]
for month in months:
setattr(self, month, np.zeros(monthly_shape))
def detrend(self, month):
# this is a dummy function that just increments
return getattr(self, month) + 1
I want to know how I can convert an input date for example if I enter 01/01/1996, the output would be "1 January 1996", I need to be able to do this for any date that is entered.
I need to use slicing.
Thank you in advance.
inLine = input("please enter a date (dd/mm/yyyy) : ").split(',')
monthNames = ("January", "February", "March", \
"April", "May", "June", \
"July", "August", "September", \
"October", "November", "December" )
month = inLine [:10]
month2 = "month"[:1]
day = inLine
year = inLine[0:2]
year2 = "year"[0:4]
print("this is the date %s %s %s." % (month2, day2, year2))
I don't know why you need split your input when datetime parsing libraries already exist in Python.
>>> from datetime import datetime
>>> datetime.strptime('01/01/1996', '%M/%d/%Y').strftime('%d %B %Y')
'01 January 1996'
This is very simplistic response. You need to go away and learn about arrays, indexing and manipulating them. I also suggest, if this is homework of some kind, you go through and do more examples and look into what happens if, for example, I enter invalid input.
inLine = input("please enter a date (dd/mm/yyyy) : ").split('/')
monthNames = ("January", "February", "March", \
"April", "May", "June", \
"July", "August", "September", \
"October", "November", "December" )
day = int(inLine[0])
month = int(inLine[1])
year = int(inLine[2])
print("this is the date %s %s %s." % (day, monthNames[month-1], year))
i have this dict:
dict_meses = {1: 'Enero', 2: 'Febrero', 3: 'Marzo', 4: 'Abril', 5: 'Mayo', 6: 'Junio', 7: 'Julio', 8: 'Agosto',
9: 'Setiembre', 10: 'Octubre', 11: 'Noviembre', 12: 'Diciembre'}
I need to change the month on a string like this '14/1/2015' for the month that corresponds in the dict. For example if a have '14/1/2015' i need to change it to '1/Enero/2015'
I am trying to do something like this:
def xxx(days): -----> days is a list of tuples like this [('14/1/2015', 500), ...]
dict_months = {1: 'Enero', 2: 'Febrero', 3: 'Marzo', 4: 'Abril', 5: 'Mayo', 6: 'Junio', 7: 'Julio', 8: 'Agosto',
9: 'Setiembre', 10: 'Octubre', 11: 'Noviembre', 12: 'Diciembre'}
days_list = []
for i in days:
lista = list(i)
fecha_entera = lista[0].split('/') ---> ['14','1','2015']
dia = fecha_entera[1] ----------------> '1'
if int(dia) in dict_meses.keys():
fecha_entera[1] = ????------------> want to change '1' to 'Enero'
dias_lista.append(fecha_entera)
return dias_lista
Question: How can i take the value that corresponds to the key that the day represents?
If i am not explaining this to clear just let me know and i will try harder.
Thanks in advance for the help provided
For a string solution, use the string "replace" function on "/1/".
lista.replace("/" + dia + "/", "/" + dict_months[int(dia)] + "/")
You can use datetime to parse your dates using %B with srftime to get the output you want:
from datetime import datetime
dte = '14/1/2015'
print(datetime.strptime(dte,"%d/%m/%Y").strftime("%d/%B/%Y"))
%B will give you the locale’s full month name.
In [1]: from datetime import datetime
In [2]: dte = '14/1/2015'
In [3]: import locale
In [4]: locale.setlocale(locale.LC_ALL,"es_SV.utf_8")
Out[4]: 'es_SV.utf_8'
In [5]: print(datetime.strptime(dte,"%d/%m/%Y").strftime("%d/%B/%Y"))
14/enero/2015
If every first element is a date string:
def xxx(days):
return [datetime.strptime(dte, "%d/%m/%Y").strftime("%d/%B/%Y")
for dte, _ in days]
If you want to use your dict:
def xxx(days):
dict_months = {"1": 'Enero', "2": 'Febrero', "3": 'Marzo', "4": 'Abril', "5": 'Mayo', "6": 'Junio', "7": 'Julio',
"8": 'Agosto',
"9": 'Setiembre', "10": 'Octubre', "11": 'Noviembre', "12": 'Diciembre'}
days_list = []
for sub in map(list, days):
dy, mn, year = sub[0].split()
days_list.append("{}/{}/{}".format(dy, dict_months[mn], year))
return days_list
You should use the keys as strings, it is pointless having to cast to int to compare.