In this code (reproducible example), I want to generate a dataframe composed by random dates in the first col, and by random numbers (in reality they will be generate from a socket) in the second column.
Another important feature I want to keep is that: since I need to update this date every n-period, a "missmatch" can happen (network connection failure), I need to have the dataset without repetitions (previous data) in it.
I created three functions: randomGen()
, df_Gen()
for generate the dataframe, entryPoint()
finds the correct date so that it will not include any repeated/previous data, avoiding this mistake.
Since I come from an R and C++ knowledge of coding, I still follow this type of coding. So my feeling is that the code can be optimized a lot, but for now I don't know what to look for or optimize.
from datetime import datetime
from datetime import timedelta
import datetime
import time
import pandas as pd
import math
from random import gauss
import numpy as np
##CREATING DATETIME OBJECT
l = list()
num = list()
num = pd.DataFrame(num)
n = 10
df = []
data = []
data = pd.DataFrame(data)
date_temp = []
date_temp = pd.DataFrame(date_temp)
#iteration
i = 0
last_data = 0
dt_0 = datetime.datetime(year=2020,month=12,day=11,hour=12,minute=30,second=14)
#increment by 1 minute
dt_1 = dt_0+timedelta(hours=0,minutes=1,seconds=0)
dt_2 = dt_1.strftime("%Y/%m/%d %H:%M:%S") ##trasform in string type(dt_1.strftime("%Y/%m/%d %H:%M:%S")) -> 'str'
def randomGen():
global num
my_mean = 10
my_variance = 5
random_numbers = [gauss(my_mean, math.sqrt(my_variance)) for x in range(n)]
num = random_numbers
num = pd.DataFrame(num) ##pd Dataframe
print("num:",num)
print("")
return num
def entryPoint():
global last_date, idx_start, row2delete
last_date = t1[0][0]
for x in range(len(t0)): #np.intersect1d(t0,t1)
print("x:",x)
if last_date==t0[0][x]:
idx_start = x
print(idx_start)
def df_Gen():
global l,df,data,data_temp,i,dt_0,t0,t1
for x in range(n): #generating 1 minutes date
dt_1 = dt_0 + timedelta(hours=0, minutes=x, seconds=0)
dt_2 = dt_1.strftime("%Y/%m/%d %H:%M:%S")
l.append(dt_2)
if i==0: #enter here once
df = pd.DataFrame(l)
data_temp = pd.concat([df, num], axis=1) #cbind random num and dates
data_temp = data_temp.T.reset_index(drop=True).T ##reset column index
data = data_temp
t0 = df
print("data:",data)
print("")
data_temp = []
l = []
if i>0:
df = pd.DataFrame(l)
data_temp = pd.concat([df, num], axis=1) #cbind random num and dates
data_temp = data_temp.T.reset_index(drop=True).T ##reset column index
t1 = df
entryPoint()
#data.drop(index=data.index[:3],axis=0) #delete first 3 rows
data = data.head(idx_start) ##keep first idx_start rows
data = pd.concat([data,data_temp])
data = data.reset_index() #reset rownames
print("data:",data)
print("")
print("data_temp:",data_temp)
print("")
data_temp = []
l = []
#increasing by 5 minutes to create a missmatch between "data" and the next "data_temp"
dt_0 = dt_0+timedelta(hours=0, minutes=5, seconds=0)
print("i:",i)
print("")
print("")
i = i + 1
#### RUN ####
randomGen()
for j in range(2):
df_Gen()
print("data:",data)
How can I optimize this code? Is this a correct way of think an algorithm like this? Any suggestion is welcomed.
1 Answer 1
I tried to understand this code; I really did. I'm afraid that none of it is redeemable. It's a very severe mix of:
- global state; none of these variables should be globals
- surprise side-effects in every function due to reliance on globals
- inappropriate reuse of variables instead of letting variables go out of scope
- a mishmash of native datetimes (don't use those in Pandas) and datetime-formatted strings (don't use those either)
It's also wrong if you try to run it any longer than its current bound. If you increase the outer loop from range(2)
to range(4)
it implodes because of an ever-growing number of index resets that eventually cause a fatal column duplicate.
This goal:
I want to generate a dataframe composed by random dates in the first col,
simply didn't happen. You made the datetimes monotonic and regular; that isn't random.
I'm going to try and be charitable and make a wild guess at what this tried to do:
import itertools
import typing
import numpy as np
import pandas as pd
ONE_MINUTE = pd.Timedelta(1, unit='min')
def random_gen_block(
rand: np.random.Generator,
start: pd.Timestamp,
n: int = 10,
mean: float = 10,
variance: float = 5,
) -> pd.Series:
stdev = np.sqrt(variance)
block = pd.Series(
name='num',
index=pd.date_range(
name='datetime', inclusive='left',
start=start, periods=n, freq='min',
),
data=rand.normal(loc=mean, scale=stdev, size=n),
)
return block
def random_gen_stream() -> typing.Iterator[pd.Series]:
rand = np.random.default_rng(seed=0)
start = pd.Timestamp(year=2020, month=12, day=11, hour=12, minute=30, second=14)
n = 10
block = random_gen_block(rand=rand, start=start, n=n)
while True:
yield block
n_to_repeat = rand.integers(low=0, high=n, endpoint=True)
repeated = block.iloc[-n_to_repeat:]
new = random_gen_block(
rand=rand, n=n, start=repeated.index[-1] + ONE_MINUTE,
)
block = pd.concat((repeated, new))
def build() -> None:
stream = random_gen_stream()
nums = next(stream)
print('First block:')
print(nums)
print()
for block in itertools.islice(stream, 4):
print('Adding block:')
print(block)
print()
# Favour new data over old data
nums = block.combine_first(nums)
pd.options.display.max_rows = 99
print('Aggregated:')
print(nums)
if __name__ == '__main__':
build()
First block:
datetime
2020年12月11日 12:30:14 10.281141
2020年12月11日 12:31:14 9.704605
2020年12月11日 12:32:14 11.432029
2020年12月11日 12:33:14 10.234564
2020年12月11日 12:34:14 8.802207
2020年12月11日 12:35:14 10.808551
2020年12月11日 12:36:14 12.915833
2020年12月11日 12:37:14 12.117737
2020年12月11日 12:38:14 8.426400
2020年12月11日 12:39:14 7.170432
Freq: min, Name: num, dtype: float64
Adding block:
datetime
2020年12月11日 12:37:14 12.117737
2020年12月11日 12:38:14 8.426400
2020年12月11日 12:39:14 7.170432
2020年12月11日 12:40:14 10.092408
2020年12月11日 12:41:14 4.801073
2020年12月11日 12:42:14 9.510767
2020年12月11日 12:43:14 7.214058
2020年12月11日 12:44:14 8.362600
2020年12月11日 12:45:14 8.783000
2020年12月11日 12:46:14 9.292731
2020年12月11日 12:47:14 10.920434
2020年12月11日 12:48:14 12.331131
2020年12月11日 12:49:14 9.712588
Freq: min, Name: num, dtype: float64
Adding block:
datetime
2020年12月11日 12:42:14 9.510767
2020年12月11日 12:43:14 7.214058
2020年12月11日 12:44:14 8.362600
2020年12月11日 12:45:14 8.783000
2020年12月11日 12:46:14 9.292731
2020年12月11日 12:47:14 10.920434
2020年12月11日 12:48:14 12.331131
2020年12月11日 12:49:14 9.712588
2020年12月11日 12:50:14 13.055505
2020年12月11日 12:51:14 8.512579
2020年12月11日 12:52:14 10.786000
2020年12月11日 12:53:14 12.020221
2020年12月11日 12:54:14 10.210218
2020年12月11日 12:55:14 8.337485
2020年12月11日 12:56:14 7.938959
2020年12月11日 12:57:14 8.976494
2020年12月11日 12:58:14 10.492371
2020年12月11日 12:59:14 7.742425
Freq: min, Name: num, dtype: float64
Adding block:
datetime
2020年12月11日 12:53:14 12.020221
2020年12月11日 12:54:14 10.210218
2020年12月11日 12:55:14 8.337485
2020年12月11日 12:56:14 7.938959
2020年12月11日 12:57:14 8.976494
2020年12月11日 12:58:14 10.492371
2020年12月11日 12:59:14 7.742425
2020年12月11日 13:00:14 9.643962
2020年12月11日 13:01:14 11.209367
2020年12月11日 13:02:14 10.479992
2020年12月11日 13:03:14 10.794638
2020年12月11日 13:04:14 8.537995
2020年12月11日 13:05:14 9.710175
2020年12月11日 13:06:14 11.753022
2020年12月11日 13:07:14 13.339414
2020年12月11日 13:08:14 7.184644
2020年12月11日 13:09:14 13.385236
Freq: min, Name: num, dtype: float64
Adding block:
datetime
2020年12月11日 13:06:14 11.753022
2020年12月11日 13:07:14 13.339414
2020年12月11日 13:08:14 7.184644
2020年12月11日 13:09:14 13.385236
2020年12月11日 13:10:14 13.009469
2020年12月11日 13:11:14 11.747065
2020年12月11日 13:12:14 10.591341
2020年12月11日 13:13:14 9.298047
2020年12月11日 13:14:14 13.260233
2020年12月11日 13:15:14 14.383271
2020年12月11日 13:16:14 14.028578
2020年12月11日 13:17:14 12.940661
2020年12月11日 13:18:14 10.799127
2020年12月11日 13:19:14 7.298117
Freq: min, Name: num, dtype: float64
Aggregated:
datetime
2020年12月11日 12:30:14 10.281141
2020年12月11日 12:31:14 9.704605
2020年12月11日 12:32:14 11.432029
2020年12月11日 12:33:14 10.234564
2020年12月11日 12:34:14 8.802207
2020年12月11日 12:35:14 10.808551
2020年12月11日 12:36:14 12.915833
2020年12月11日 12:37:14 12.117737
2020年12月11日 12:38:14 8.426400
2020年12月11日 12:39:14 7.170432
2020年12月11日 12:40:14 10.092408
2020年12月11日 12:41:14 4.801073
2020年12月11日 12:42:14 9.510767
2020年12月11日 12:43:14 7.214058
2020年12月11日 12:44:14 8.362600
2020年12月11日 12:45:14 8.783000
2020年12月11日 12:46:14 9.292731
2020年12月11日 12:47:14 10.920434
2020年12月11日 12:48:14 12.331131
2020年12月11日 12:49:14 9.712588
2020年12月11日 12:50:14 13.055505
2020年12月11日 12:51:14 8.512579
2020年12月11日 12:52:14 10.786000
2020年12月11日 12:53:14 12.020221
2020年12月11日 12:54:14 10.210218
2020年12月11日 12:55:14 8.337485
2020年12月11日 12:56:14 7.938959
2020年12月11日 12:57:14 8.976494
2020年12月11日 12:58:14 10.492371
2020年12月11日 12:59:14 7.742425
2020年12月11日 13:00:14 9.643962
2020年12月11日 13:01:14 11.209367
2020年12月11日 13:02:14 10.479992
2020年12月11日 13:03:14 10.794638
2020年12月11日 13:04:14 8.537995
2020年12月11日 13:05:14 9.710175
2020年12月11日 13:06:14 11.753022
2020年12月11日 13:07:14 13.339414
2020年12月11日 13:08:14 7.184644
2020年12月11日 13:09:14 13.385236
2020年12月11日 13:10:14 13.009469
2020年12月11日 13:11:14 11.747065
2020年12月11日 13:12:14 10.591341
2020年12月11日 13:13:14 9.298047
2020年12月11日 13:14:14 13.260233
2020年12月11日 13:15:14 14.383271
2020年12月11日 13:16:14 14.028578
2020年12月11日 13:17:14 12.940661
2020年12月11日 13:18:14 10.799127
2020年12月11日 13:19:14 7.298117
Freq: min, Name: num, dtype: float64