volue-insight-timeseries 1.2.2__tar.gz → 1.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of volue-insight-timeseries might be problematic. Click here for more details.
- {volue_insight_timeseries-1.2.2 → volue_insight_timeseries-1.2.3}/PKG-INFO +1 -1
- volue_insight_timeseries-1.2.3/volue_insight_timeseries/VERSION +1 -0
- {volue_insight_timeseries-1.2.2 → volue_insight_timeseries-1.2.3}/volue_insight_timeseries/util.py +77 -59
- {volue_insight_timeseries-1.2.2 → volue_insight_timeseries-1.2.3}/volue_insight_timeseries.egg-info/PKG-INFO +1 -1
- volue_insight_timeseries-1.2.2/volue_insight_timeseries/VERSION +0 -1
- {volue_insight_timeseries-1.2.2 → volue_insight_timeseries-1.2.3}/LICENSE +0 -0
- {volue_insight_timeseries-1.2.2 → volue_insight_timeseries-1.2.3}/MANIFEST.in +0 -0
- {volue_insight_timeseries-1.2.2 → volue_insight_timeseries-1.2.3}/README.md +0 -0
- {volue_insight_timeseries-1.2.2 → volue_insight_timeseries-1.2.3}/setup.cfg +0 -0
- {volue_insight_timeseries-1.2.2 → volue_insight_timeseries-1.2.3}/setup.py +0 -0
- {volue_insight_timeseries-1.2.2 → volue_insight_timeseries-1.2.3}/volue_insight_timeseries/__init__.py +0 -0
- {volue_insight_timeseries-1.2.2 → volue_insight_timeseries-1.2.3}/volue_insight_timeseries/auth.py +0 -0
- {volue_insight_timeseries-1.2.2 → volue_insight_timeseries-1.2.3}/volue_insight_timeseries/curves.py +0 -0
- {volue_insight_timeseries-1.2.2 → volue_insight_timeseries-1.2.3}/volue_insight_timeseries/events.py +0 -0
- {volue_insight_timeseries-1.2.2 → volue_insight_timeseries-1.2.3}/volue_insight_timeseries/session.py +0 -0
- {volue_insight_timeseries-1.2.2 → volue_insight_timeseries-1.2.3}/volue_insight_timeseries.egg-info/SOURCES.txt +0 -0
- {volue_insight_timeseries-1.2.2 → volue_insight_timeseries-1.2.3}/volue_insight_timeseries.egg-info/dependency_links.txt +0 -0
- {volue_insight_timeseries-1.2.2 → volue_insight_timeseries-1.2.3}/volue_insight_timeseries.egg-info/requires.txt +0 -0
- {volue_insight_timeseries-1.2.2 → volue_insight_timeseries-1.2.3}/volue_insight_timeseries.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
1.2.3
|
{volue_insight_timeseries-1.2.2 → volue_insight_timeseries-1.2.3}/volue_insight_timeseries/util.py
RENAMED
|
@@ -10,6 +10,7 @@ import pandas as pd
|
|
|
10
10
|
import numpy as np
|
|
11
11
|
import warnings
|
|
12
12
|
from past.types import basestring
|
|
13
|
+
|
|
13
14
|
try:
|
|
14
15
|
from urllib.parse import quote_plus
|
|
15
16
|
except ImportError:
|
|
@@ -19,44 +20,45 @@ from zoneinfo._common import ZoneInfoNotFoundError
|
|
|
19
20
|
|
|
20
21
|
|
|
21
22
|
# Curve types
|
|
22
|
-
TIME_SERIES =
|
|
23
|
-
TAGGED =
|
|
24
|
-
INSTANCES =
|
|
25
|
-
TAGGED_INSTANCES =
|
|
23
|
+
TIME_SERIES = "TIME_SERIES"
|
|
24
|
+
TAGGED = "TAGGED"
|
|
25
|
+
INSTANCES = "INSTANCES"
|
|
26
|
+
TAGGED_INSTANCES = "TAGGED_INSTANCES"
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
# Frequency mapping from TS to Pandas
|
|
29
30
|
_TS_FREQ_TABLE = {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
31
|
+
"Y": "YS",
|
|
32
|
+
"S": "2QS",
|
|
33
|
+
"Q": "QS",
|
|
34
|
+
"M": "MS",
|
|
35
|
+
"W": "W-MON",
|
|
36
|
+
"H12": "12h",
|
|
37
|
+
"H6": "6h",
|
|
38
|
+
"H3": "3h",
|
|
39
|
+
"H": "h",
|
|
40
|
+
"MIN30": "30min",
|
|
41
|
+
"MIN15": "15min",
|
|
42
|
+
"MIN5": "5min",
|
|
43
|
+
"MIN": "min",
|
|
44
|
+
"D": "D",
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
# Mapping from various versions of Pandas to TS is built from map above,
|
|
46
48
|
# with some additions to support older versions of pandas
|
|
47
49
|
_PANDAS_FREQ_TABLE = {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
50
|
+
"YS-JAN": "Y",
|
|
51
|
+
"AS-JAN": "Y",
|
|
52
|
+
"AS": "Y",
|
|
53
|
+
"2QS-JAN": "S",
|
|
54
|
+
"QS-JAN": "Q",
|
|
55
|
+
"12H": "H12",
|
|
56
|
+
"6H": "H6",
|
|
57
|
+
"3H": "H3",
|
|
58
|
+
"30T": "MIN30",
|
|
59
|
+
"15T": "MIN15",
|
|
60
|
+
"5T": "MIN5",
|
|
61
|
+
"T": "MIN",
|
|
60
62
|
}
|
|
61
63
|
for ts_freq, pandas_freq in _TS_FREQ_TABLE.items():
|
|
62
64
|
_PANDAS_FREQ_TABLE[pandas_freq.upper()] = ts_freq
|
|
@@ -70,8 +72,10 @@ class TS(object):
|
|
|
70
72
|
"""
|
|
71
73
|
A class to hold a basic time series.
|
|
72
74
|
"""
|
|
73
|
-
|
|
74
|
-
|
|
75
|
+
|
|
76
|
+
def __init__(
|
|
77
|
+
self, id=None, name=None, frequency=None, time_zone=None, tag=None, issue_date=None, curve_type=None, points=None, input_dict=None
|
|
78
|
+
):
|
|
75
79
|
self.id = id
|
|
76
80
|
self.name = name
|
|
77
81
|
self.frequency = frequency
|
|
@@ -89,19 +93,19 @@ class TS(object):
|
|
|
89
93
|
if self.time_zone is not None:
|
|
90
94
|
self.tz = parse_tz(self.time_zone)
|
|
91
95
|
else:
|
|
92
|
-
self.tz = ZoneInfo(
|
|
96
|
+
self.tz = ZoneInfo("CET")
|
|
93
97
|
|
|
94
98
|
if self.curve_type is None:
|
|
95
99
|
self.curve_type = detect_curve_type(self.issue_date, self.tag)
|
|
96
100
|
# Validation
|
|
97
101
|
if self.frequency is None:
|
|
98
|
-
raise CurveException(
|
|
102
|
+
raise CurveException("TS must have frequency")
|
|
99
103
|
|
|
100
104
|
def __str__(self):
|
|
101
|
-
size =
|
|
105
|
+
size = ""
|
|
102
106
|
if self.points:
|
|
103
|
-
size =
|
|
104
|
-
return
|
|
107
|
+
size = " size: {}".format(len(self.points))
|
|
108
|
+
return "TS: {}{}".format(self.fullname, size)
|
|
105
109
|
|
|
106
110
|
@property
|
|
107
111
|
def fullname(self):
|
|
@@ -116,10 +120,10 @@ class TS(object):
|
|
|
116
120
|
attrs.append(self.tag)
|
|
117
121
|
if self.issue_date:
|
|
118
122
|
attrs.append(str(self.issue_date))
|
|
119
|
-
return
|
|
123
|
+
return " ".join(attrs)
|
|
120
124
|
|
|
121
125
|
def to_pandas(self, name=None):
|
|
122
|
-
"""
|
|
126
|
+
"""Converting :class:`volue_insight_timeseries.util.TS` object
|
|
123
127
|
to a pandas.Series object
|
|
124
128
|
|
|
125
129
|
Parameters
|
|
@@ -134,18 +138,32 @@ class TS(object):
|
|
|
134
138
|
if name is None:
|
|
135
139
|
name = self.fullname
|
|
136
140
|
if self.points is None or len(self.points) == 0:
|
|
137
|
-
return pd.Series(name=name, dtype=
|
|
141
|
+
return pd.Series(name=name, dtype="float64")
|
|
138
142
|
|
|
139
143
|
index = []
|
|
140
144
|
values = []
|
|
141
145
|
for row in self.points:
|
|
142
146
|
if len(row) != 2:
|
|
143
|
-
raise ValueError(
|
|
147
|
+
raise ValueError("Points have unexpected contents")
|
|
144
148
|
dt = datetime.datetime.fromtimestamp(row[0] / 1000.0, self.tz)
|
|
145
149
|
index.append(dt)
|
|
146
150
|
values.append(row[1])
|
|
147
151
|
res = pd.Series(name=name, index=index, data=values)
|
|
148
|
-
|
|
152
|
+
mapped_freq = res.asfreq(self._map_freq(self.frequency))
|
|
153
|
+
dropped = mapped_freq.dropna()
|
|
154
|
+
|
|
155
|
+
# Warn about edge case for Gas Day timezone during DST changes.
|
|
156
|
+
# Gas Day is a 24-hour period starting at 4:00 UTC in summer and 5:00 UTC in winter,
|
|
157
|
+
# and finishing at 4:00 UTC (or 5:00) the next day. corresponding to 6:00 local time in Germany year-round.
|
|
158
|
+
# A gas loader bug causes timestamps on the day after DST to shift to 5:00 or 7:00 instead of 6:00.
|
|
159
|
+
if len(self.points) != len(dropped):
|
|
160
|
+
warnings.warn(
|
|
161
|
+
f"Data length mismatch: original data length is {len(self.points)}, but mapped frequency data length is "
|
|
162
|
+
f"{len(dropped)}. This may indicate data truncation.",
|
|
163
|
+
RuntimeWarning,
|
|
164
|
+
stacklevel=2,
|
|
165
|
+
)
|
|
166
|
+
return mapped_freq
|
|
149
167
|
|
|
150
168
|
@staticmethod
|
|
151
169
|
def from_pandas(pd_series):
|
|
@@ -183,7 +201,7 @@ class TS(object):
|
|
|
183
201
|
|
|
184
202
|
@staticmethod
|
|
185
203
|
def sum(ts_list, name):
|
|
186
|
-
"""
|
|
204
|
+
"""calculate the sum of a given list
|
|
187
205
|
of :class:`volue_insight_timeseries.util.TS` objects
|
|
188
206
|
|
|
189
207
|
Returns a :class:`~volue_insight_timeseries.util.TS`
|
|
@@ -205,7 +223,7 @@ class TS(object):
|
|
|
205
223
|
|
|
206
224
|
@staticmethod
|
|
207
225
|
def mean(ts_list, name):
|
|
208
|
-
"""
|
|
226
|
+
"""calculate the mean of a given list of TS objects
|
|
209
227
|
|
|
210
228
|
Returns a TS (:class:`volue_insight_timeseries.util.TS`) object that is
|
|
211
229
|
the mean of a list of TS objects with the given name.
|
|
@@ -225,7 +243,7 @@ class TS(object):
|
|
|
225
243
|
|
|
226
244
|
@staticmethod
|
|
227
245
|
def median(ts_list, name):
|
|
228
|
-
"""
|
|
246
|
+
"""calculate the median of a given list of TS objects
|
|
229
247
|
|
|
230
248
|
Returns a TS (:class:`volue_insight_timeseries.util.TS`) object that is
|
|
231
249
|
the median of a list of TS objects with the given name.
|
|
@@ -297,10 +315,10 @@ def parserange(rangeobj, tz=None):
|
|
|
297
315
|
"""
|
|
298
316
|
Parse a range object (a pair of date strings, which may each be None)
|
|
299
317
|
"""
|
|
300
|
-
if rangeobj.get(
|
|
318
|
+
if rangeobj.get("empty") is True:
|
|
301
319
|
return None
|
|
302
|
-
begin = rangeobj.get(
|
|
303
|
-
end = rangeobj.get(
|
|
320
|
+
begin = rangeobj.get("begin")
|
|
321
|
+
end = rangeobj.get("end")
|
|
304
322
|
if begin is not None:
|
|
305
323
|
begin = parsetime(begin, tz=tz)
|
|
306
324
|
if end is not None:
|
|
@@ -309,13 +327,13 @@ def parserange(rangeobj, tz=None):
|
|
|
309
327
|
|
|
310
328
|
|
|
311
329
|
_tzmap = {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
330
|
+
"CEGT": "CET",
|
|
331
|
+
"WEGT": "WET",
|
|
332
|
+
"PST": "US/Pacific",
|
|
333
|
+
"TRT": "Turkey",
|
|
334
|
+
"MSK": "Europe/Moscow",
|
|
335
|
+
"ART": "America/Argentina/Buenos_Aires",
|
|
336
|
+
"JST": "Asia/Tokyo",
|
|
319
337
|
}
|
|
320
338
|
|
|
321
339
|
|
|
@@ -325,7 +343,7 @@ def parse_tz(time_zone):
|
|
|
325
343
|
time_zone = _tzmap[time_zone]
|
|
326
344
|
return ZoneInfo(time_zone)
|
|
327
345
|
except ZoneInfoNotFoundError:
|
|
328
|
-
return ZoneInfo(
|
|
346
|
+
return ZoneInfo("CET")
|
|
329
347
|
|
|
330
348
|
|
|
331
349
|
def detect_curve_type(issue_date, tag):
|
|
@@ -348,12 +366,12 @@ def is_integer(s):
|
|
|
348
366
|
|
|
349
367
|
|
|
350
368
|
def make_arg(key, value):
|
|
351
|
-
if hasattr(value,
|
|
352
|
-
return
|
|
369
|
+
if hasattr(value, "__iter__") and not isinstance(value, basestring):
|
|
370
|
+
return "&".join([make_arg(key, v) for v in value])
|
|
353
371
|
|
|
354
372
|
if isinstance(value, datetime.date):
|
|
355
373
|
tmp = value.isoformat()
|
|
356
374
|
else:
|
|
357
|
-
tmp =
|
|
375
|
+
tmp = "{}".format(value)
|
|
358
376
|
v = quote_plus(tmp)
|
|
359
|
-
return
|
|
377
|
+
return "{}={}".format(key, v)
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
1.2.2
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{volue_insight_timeseries-1.2.2 → volue_insight_timeseries-1.2.3}/volue_insight_timeseries/auth.py
RENAMED
|
File without changes
|
{volue_insight_timeseries-1.2.2 → volue_insight_timeseries-1.2.3}/volue_insight_timeseries/curves.py
RENAMED
|
File without changes
|
{volue_insight_timeseries-1.2.2 → volue_insight_timeseries-1.2.3}/volue_insight_timeseries/events.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|