How to generate random time series data including February with 29 days? - python

I have used the following codes to generate a random rainfall data from 1950 to 2009 with known probability, mean and standard deviations. But, I have been suffering from iterating the days of February as 29 days in the leap years. And, also I was trying to save the output in a text file, but it gives an error message like
TypeError: float argument required, not numpy.string_
Can anyone please help me out?
My code:
import numpy as np
import random
import itertools
import datetime
dry =[0.33,0.27,0.32,0.41,0.42,0.45,0.57,0.52,0.45,0.39,0.37,0.37]
wet = [0.66,0.72,0.67,0.58,0.57,0.54,0.42,0.47,0.54,0.60,0.62,0.62]
d2d_tran = [0.56,0.50,0.58,0.62,0.63,0.67,0.73,0.66,0.60,0.56,0.57,0.62]
w2w_tran = [0.78,0.80,0.79,0.73,0.72,0.72,0.63,0.64,0.66,0.71,0.74,0.76]
mu = [3.71, 4.46, 4.11, 2.94, 3.00, 2.87, 2.31, 2.44, 2.56, 3.45, 4.32, 4.12]
sigma = [6.72,7.92,7.49,6.57,6.09,5.53,4.38,4.69,4.31,5.71,7.64,7.54]
days = [31,28,31,30,31,30,31,31,30,31,30,31]
rain = []
for y in xrange(0,60):
for m in xrange(0,12):
random_num = np.random.rand(days[m])
if random.random() <= dry[m]:
random_num[0] = 0
else:
r = abs(random.gauss(mu[m],sigma[m]))
random_num[0] = r
for i in xrange(1,days[m]):
if random_num[i-1] == 0:
if random_num[i] <= d2d_tran[m]:
random_num[i] = 0
else:
r = abs(random.gauss(mu[m],sigma[m]))
random_num[i] = r
else:
if random_num[i] <= w2w_tran[m]:
r = abs(random.gauss(mu[m],sigma[m]))
random_num[i] = r
else:
random_num[i] = 0
rain.append(random_num)
rain_series = []
for j in itertools.chain.from_iterable(rain):
rain_series.append(j)
y = np.array(rain_series).reshape(-1, 1)
date_series = []
def generate_dates(start_date, end_date):
return (start_date + datetime.timedelta(days=d) for d in xrange((end_date - start_date).days + 1))
start_date = datetime.date(1950, 1, 1)
end_date = datetime.date(2009, 12, 16)
for current_date in generate_dates(start_date, end_date):
f = current_date.strftime('%Y-%m-%d')
date_series.append(f)
z = np.array(date_series).reshape(-1, 1)
#### Here I have 365x60 = 21900 rainfall values, that is why I had to
####set the end_date upto (2009,12,16). If
#### the February days for leap years can be set as 29 in days[] of
####rain_series than this problem would be solved.
data = np.concatenate((z,y), axis=1)
print data
data1 = data.reshape((21900,2))
np.savetxt('Random Rainfall Data.txt', data1)
#### I want to shape data in two columns like dates and rainfall.
#### And than, save it into a text file. But, it provides an error!!!

Use the calendar.monthrange() to get the number of days of a month.
for year in xrange(1950,2020):
for month in xrange(1,13):
day_num = calendar.monthrange(year, month)[1]
random_num = np.random.rand(day_num)
...

Regarding the data writing problem, you must add a third argument. It depends on your specific problem:
np.savetxt('test.txt', a, '%s') # Example
See documentation for more formatting info.

Related

(Python) How can I make a progam that calculates how many days someone has been alive?

Im new to python and im wondering if someone could help me make a program that calculates your days alive from a date of birth. I do not want to use the datetime library. Any help would be really appreciated!
This is what I have got so far:
date_of_birth = (input("Enter Date of Birth (YYYY/MM/DD):"))
now_date = ("2021/09/11")
days = date_of_birth[8:10]
months = date_of_birth[5:7]
years = date_of_birth[0:4]
if len(date_of_birth) == 10:
print ("Working")
else:
print ("Invalid date of birth")
Please use strptime to parse a date string into a datetime object:
import datetime
birthdate = datetime.datetime.strptime(birthdate_str, '%Y/%m/%d')
now = datetime.datetime.now()
Then subtraction between two datetime objects returns a timedelta object, from which you can read the days attribute:
print((now - birthdate).days)
EDIT:
To do it without the datetime library, you can convert a date to number of days (i.e. since 0/0/0) and do the arithmetic subtraction:
def date_to_days(y, m, d):
monthDays = [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
n = y * 365 + d
for i in range(m):
n += monthDays[i]
l = y # leap days count
if m <= 2: l -= 1
l = l // 4 - l // 100 + l // 400
n += l
return n
def date_diff(y1, m1, d1, y2, m2, d2):
return date_to_days(y2, m2, d2) - date_to_days(y1, m1, d1)

Difference between two dates ignoring year

Python datetime objects require a year, however I would just like to write a function that outputs the differences in dates between two day-months ignoring year. Meaning the output range of this function is [-182, 183], since the calculations should "wrap around" the year.
Example:
Goal date: 1st Jan
Guess: 31st Dec
Result: -1
Goal date: 1st Jan
Guess: 2nd Jan
Result: +1
def date_diff(goal, guess):
#goal and guess are in the format "%m-%d"
goal_date = datetime.strptime(goal + "-2020", "%m-%d-%Y")
goal_date1 = datetime.strptime(goal + "-2021", "%m-%d-%Y")
guess_date = datetime.strptime(guess + "-2020", "%m-%d-%Y")
guess_date1 = datetime.strptime(guess + "-2021", "%m-%d-%Y")
r1 = goal_date - guess_date
r1 = r1.days
r3 = goal_date1 - guess_date
r3 = r3.days
r2 = guess_date1 - goal_date
r2 = r2.days
r4 = guess_date - goal_date
r4 = r4.days
r = ((r1, math.copysign(1, r1)), (r2, math.copysign(1, r2)),(r3, math.copysign(1, r2)),(r4, math.copysign(1, r4)))
#idea here was the find min of index 0 of each tuple then restore the sign, but i think i'm missing some combinations
smallest = min(r, key = lambda x:abs(x[0]))
return smallest[0]*smallest[1]
You can take the minimum (absolute) difference with the second date at the previous, same and next year of the first date
For example :
from datetime import date
def dateDelta(d1,d2):
return min(((date(d1.year+i,d2.month,d2.day)-d1).days
for i in (-1,0,1)),key=abs)
d1 = date(2002,10,15)
d2 = date(2002,2,3)
print(dateDelta(d1,d2)) # 111
print(dateDelta(d2,d1)) # -111
Note that you may get varying results depending on the reference year you chose. To avoid interference from leap years, select a non-leap year for d1 that is neither before nor after a leap year (e.g. 2002, or any year mod 4 == 2)

How to solve the weekday function problem Python

I am very new to Python and we were told to write the weekday function without any modules like e.g. daytime etc.
But it doesn't work and i am not sure where is a problem
def weekDay (day,month,year):
global y0
global m0
global x
y0 = 0
m0 = 0
day,month,year = int(input("Enter a day: "))
month = int(input("Enter a month: "))
year = int(input("Enter a year:"))
a = (day + x + (31 * m0) // 12) % 7
for m0 in a:
m0 = month + 12 * ((14 - month) // 12) - 2
for x in a:
x = y0 + y0 // 4 - y0 // 100 + y0 // 400
for y0 in x:
y0 = year - ((14 - month) // 12)
if a == 0:
print("Sunday")
elif a == 1:
print("Monday")
elif a == 2:
print("Tuesday")
elif a == 3:
print("Wednesday")
elif a == 4:
print("Thursday")
elif a == 5:
print("Friday")
else:
print("Error")
return weekDay(a)
'''
here is the formula we were given:
[![formula][1]][1]
[1]: https://i.stack.imgur.com/iBv30.png
This should help:
>>> import datetime
>>> now = datetime.datetime.now()
>>> now.strftime('%A')
'Friday'
>>>
Global variables not defined anywhere and I am not able to understand the logic you are trying to write. So written a function based on a aptitude trick.
def weekday(day,month,year):
"""
This function is written based upon aptitude trick
to obtain day from given a date.
Input date example : 15-5-2020
Link for logic : https://www.youtube.com/watch?v=rJ0_GWDTdD4
"""
# for different months we are assigning specific number to that month
months = {1:1, 2:4, 3:4, 4:0, 5:2, 6:5, 7:0, 8:3, 9:6, 10:1, 11:4, 12:6}
# assigning days to a number
day_name = {1:'Sunday', 2:'Monday', 3:'Tuesday', 4:'Wednesday', 5:'Thursday',
6:'Friday', 0:'Saturday'}
# to get the year in between 1600 and 2000. since we are assiging values
# for the years also
while year not in range(1600,2000):
if year>2000:
year-=400
if year<1600:
year+=400
# assigning values to years
if year in range(1600,1700):
yr = 6
if year in range(1700,1800):
yr = 4
if year in range(1800,1900):
yr = 2
if year in range(1900,2000):
yr = 0
# assigning last two numbers of year to last
first = year//100
last = year - (first * 100)
# obtaining remainder
res = (day + months[month] + yr + last + (last//4))%7
#returning the day_name
return day_name[res]
day,month,year = list(map(int,input("Enter date in format dd-mm-yyyy : ").split('-')))
print(weekday(day,month,year))
Hope, you are satisfied with logic.

Making a time adding function in python

I'm trying to build a function that recieves a date and adds days, updating everything in case it changes, so far i've come up with this:
def addnewDate(date, numberOfDays):
date = date.split(":")
day = int(date[0])
month = int(date[1])
year = int(date[2])
new_days = 0
l = 0
l1 = 28
l2 = 30
l3 = 31
#l's are the accordingly days of the month
while numberOfDays > l:
numberOfDays = numberOfDays - l
if month != 12:
month += 1
else:
month = 1
year += 1
if month in [1, 3, 5, 7, 8, 10, 12]:
l = l3
elif month in [4, 6, 9, 11]:
l = l2
else:
l = l1
return str(day) + ':' + str(month) + ':' + str(year) #i'll deal
#with fact that it doesn't put the 0's in the < 10 digits later
Desired output:
addnewDate('29:12:2016', 5):
'03:01:2017'
I think the problem is with either the variables, or the position i'm using them in, kinda lost though..
Thanks in advance!
p.s I can't use python build in functions :)
Since you cannot use standard library, here's my attempt. I hope I did not forget anything.
define a table for month lengths
tweak it if leap year detected (every 4 year, but special cases)
work on zero-indexed days & months, much easier
add the number of days. If lesser that current month number of days, end, else, substract current month number of days and retry (while loop)
when last month reached, increase year
add 1 to day and month in the end
code:
def addnewDate(date, numberOfDays):
month_days = [31,28,31,30,31,30,31,31,30,31,30,31]
date = date.split(":")
day = int(date[0])-1
month = int(date[1])-1
year = int(date[2])
if year%4==0 and year%400!=0:
month_days[1]+=1
new_days = 0
#l's are the accordingly days of the month
day += numberOfDays
nb_days_month = month_days[month]
done = False # since you don't want to use break, let's create a flag
while not done:
nb_days_month = month_days[month]
if day < nb_days_month:
done = True
else:
day -= nb_days_month
month += 1
if month==12:
year += 1
month = 0
return "{:02}:{:02}:{:04}".format(day+1,month+1,year)
test (may be not exhaustive):
for i in ("28:02:2000","28:02:2004","28:02:2005","31:12:2012","03:02:2015"):
print(addnewDate(i,2))
print(addnewDate(i,31))
result:
02:03:2000
31:03:2000
01:03:2004
30:03:2004
02:03:2005
31:03:2005
02:01:2013
31:01:2013
05:02:2015
06:03:2015
of course, this is just for fun. Else use time or datetime modules!

Find day difference between two datetimes (excluding weekend days) in Python? [duplicate]

This question already has answers here:
Number of days between 2 dates, excluding weekends
(22 answers)
Closed 7 years ago.
The same problem to Find day difference between two dates (excluding weekend days) but it is for javascript. How to do that in Python?
Try it with scikits.timeseries:
import scikits.timeseries as ts
import datetime
a = datetime.datetime(2011,8,1)
b = datetime.datetime(2011,8,29)
diff_business_days = ts.Date('B', b) - ts.Date('B', a)
# returns 20
or with dateutil:
import datetime
from dateutil import rrule
a = datetime.datetime(2011,8,1)
b = datetime.datetime(2011,8,29)
diff_business_days = len(list(rrule.rrule(rrule.DAILY,
dtstart=a,
until=b - datetime.timedelta(days=1),
byweekday=(rrule.MO, rrule.TU, rrule.WE, rrule.TH, rrule.FR))))
scikits.timeseries look depricated : http://pytseries.sourceforge.net/
With pandas instead someone can do :
import pandas as pd
a = datetime.datetime(2015, 10, 1)
b = datetime.datetime(2015, 10, 29)
diff_calendar_days = pd.date_range(a, b).size
diff_business_days = pd.bdate_range(a, b).size
Not sure that this is the best one solution but it works for me:
from datetime import datetime, timedelta
startDate = datetime(2011, 7, 7)
endDate = datetime(2011, 10, 7)
dayDelta = timedelta(days=1)
diff = 0
while startDate != endDate:
if startDate.weekday() not in [5,6]:
diff += 1
startDate += dayDelta
Here's a O(1) complexity class solution which uses only built-in Python libraries.
It has constant performance regardless of time interval length and doesn't care about argument order.
#
# by default, the last date is not inclusive
#
def workdaycount(first, second, inc = 0):
if first == second:
return 0
import math
if first > second:
first, second = second, first
if inc:
from datetime import timedelta
second += timedelta(days=1)
interval = (second - first).days
weekspan = int(math.ceil(interval / 7.0))
if interval % 7 == 0:
return interval - weekspan * 2
else:
wdf = first.weekday()
if (wdf < 6) and ((interval + wdf) // 7 == weekspan):
modifier = 0
elif (wdf == 6) or ((interval + wdf + 1) // 7 == weekspan):
modifier = 1
else:
modifier = 2
return interval - (2 * weekspan - modifier)
#
# sample usage
#
print workdaycount(date(2011, 8, 15), date(2011, 8, 22)) # returns 5
print workdaycount(date(2011, 8, 15), date(2011, 8, 22), 1) # last date inclusive, returns 6

Categories

Resources