dataiter 2.0__tar.gz → 2.1__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.
- {dataiter-2.0 → dataiter-2.1}/PKG-INFO +1 -1
- {dataiter-2.0 → dataiter-2.1}/dataiter/__init__.py +9 -1
- {dataiter-2.0 → dataiter-2.1}/dataiter/aggregate.py +75 -34
- {dataiter-2.0 → dataiter-2.1}/dataiter/data_frame.py +257 -51
- {dataiter-2.0 → dataiter-2.1}/dataiter/deco.py +9 -0
- {dataiter-2.0 → dataiter-2.1}/dataiter/dt.py +46 -17
- {dataiter-2.0 → dataiter-2.1}/dataiter/io.py +8 -0
- {dataiter-2.0 → dataiter-2.1}/dataiter/list_of_dicts.py +3 -0
- {dataiter-2.0 → dataiter-2.1}/dataiter/test/test_aggregate.py +20 -0
- {dataiter-2.0 → dataiter-2.1}/dataiter/test/test_data_frame.py +177 -0
- {dataiter-2.0 → dataiter-2.1}/dataiter/test/test_dt.py +34 -0
- {dataiter-2.0 → dataiter-2.1}/dataiter/test/test_io.py +10 -0
- {dataiter-2.0 → dataiter-2.1}/dataiter/test/test_util.py +10 -0
- {dataiter-2.0 → dataiter-2.1}/dataiter/test/test_vector.py +11 -2
- dataiter-2.1/dataiter/test/test_window.py +112 -0
- {dataiter-2.0 → dataiter-2.1}/dataiter/util.py +34 -2
- {dataiter-2.0 → dataiter-2.1}/dataiter/vector.py +35 -15
- dataiter-2.1/dataiter/window.py +165 -0
- {dataiter-2.0 → dataiter-2.1}/pyproject.toml +1 -0
- {dataiter-2.0 → dataiter-2.1}/.gitignore +0 -0
- {dataiter-2.0 → dataiter-2.1}/AUTHORS.md +0 -0
- {dataiter-2.0 → dataiter-2.1}/COPYING +0 -0
- {dataiter-2.0 → dataiter-2.1}/README.md +0 -0
- {dataiter-2.0 → dataiter-2.1}/dataiter/dtypes.py +0 -0
- {dataiter-2.0 → dataiter-2.1}/dataiter/geojson.py +0 -0
- {dataiter-2.0 → dataiter-2.1}/dataiter/regex.py +0 -0
- {dataiter-2.0 → dataiter-2.1}/dataiter/test/__init__.py +0 -0
- {dataiter-2.0 → dataiter-2.1}/dataiter/test/test_geojson.py +0 -0
- {dataiter-2.0 → dataiter-2.1}/dataiter/test/test_list_of_dicts.py +0 -0
- {dataiter-2.0 → dataiter-2.1}/dataiter/test/test_regex.py +0 -0
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
21
|
# THE SOFTWARE.
|
|
22
22
|
|
|
23
|
-
__version__ = "2.
|
|
23
|
+
__version__ = "2.1"
|
|
24
24
|
|
|
25
25
|
#: Default amount of elements to return from :meth:`Vector.head`,
|
|
26
26
|
#: :meth:`Vector.sample` and :meth:`Vector.tail`.
|
|
@@ -89,12 +89,20 @@ from dataiter.aggregate import std
|
|
|
89
89
|
from dataiter.aggregate import sum
|
|
90
90
|
from dataiter.aggregate import var
|
|
91
91
|
|
|
92
|
+
from dataiter.window import cummax
|
|
93
|
+
from dataiter.window import cummin
|
|
94
|
+
from dataiter.window import cumsum
|
|
95
|
+
from dataiter.window import rank
|
|
96
|
+
from dataiter.window import shift
|
|
97
|
+
|
|
92
98
|
from dataiter.io import read_csv
|
|
99
|
+
from dataiter.io import read_duckdb
|
|
93
100
|
from dataiter.io import read_geojson
|
|
94
101
|
from dataiter.io import read_json
|
|
95
102
|
from dataiter.io import read_jsonl
|
|
96
103
|
from dataiter.io import read_npz
|
|
97
104
|
from dataiter.io import read_parquet
|
|
105
|
+
from dataiter.io import read_parquet_chunked
|
|
98
106
|
|
|
99
107
|
from dataiter import util
|
|
100
108
|
|
|
@@ -49,7 +49,8 @@ def all(x, *, drop_na=True):
|
|
|
49
49
|
Return whether all elements of `x` evaluate to ``True``.
|
|
50
50
|
|
|
51
51
|
If `x` is a string, return a function usable with
|
|
52
|
-
:meth:`.DataFrame.aggregate` that operates
|
|
52
|
+
:meth:`.DataFrame.aggregate` and :meth:`.DataFrame.modify` that operates
|
|
53
|
+
group-wise on column `x`.
|
|
53
54
|
|
|
54
55
|
Equivalent to ``numpy.all``, see the NumPy documentation for details:
|
|
55
56
|
https://numpy.org/doc/stable/reference/generated/numpy.all.html
|
|
@@ -86,7 +87,8 @@ def any(x, *, drop_na=True):
|
|
|
86
87
|
Return whether any element of `x` evaluates to ``True``.
|
|
87
88
|
|
|
88
89
|
If `x` is a string, return a function usable with
|
|
89
|
-
:meth:`.DataFrame.aggregate` that operates
|
|
90
|
+
:meth:`.DataFrame.aggregate` and :meth:`.DataFrame.modify` that operates
|
|
91
|
+
group-wise on column `x`.
|
|
90
92
|
|
|
91
93
|
Equivalent to ``numpy.any``, see the NumPy documentation for details:
|
|
92
94
|
https://numpy.org/doc/stable/reference/generated/numpy.any.html
|
|
@@ -107,10 +109,10 @@ def count(x="", *, drop_na=False):
|
|
|
107
109
|
Return the amount of elements in `x`.
|
|
108
110
|
|
|
109
111
|
If `x` is a string, return a function usable with
|
|
110
|
-
:meth:`.DataFrame.aggregate` that operates
|
|
111
|
-
all columns in a data frame should have the
|
|
112
|
-
rows), you can just leave the x argument at
|
|
113
|
-
will give you that row count.
|
|
112
|
+
:meth:`.DataFrame.aggregate` and :meth:`.DataFrame.modify` that operates
|
|
113
|
+
group-wise on column `x`. Since all columns in a data frame should have the
|
|
114
|
+
same amount of elements (i.e. rows), you can just leave the x argument at
|
|
115
|
+
its default blank string, which will give you that row count.
|
|
114
116
|
|
|
115
117
|
>>> di.count(di.Vector([1, 2, 3]))
|
|
116
118
|
>>> di.count()
|
|
@@ -123,6 +125,8 @@ def count(x="", *, drop_na=False):
|
|
|
123
125
|
return np.diff(starts, append=data.nrow)
|
|
124
126
|
aggregate.group_aware = True
|
|
125
127
|
return aggregate
|
|
128
|
+
if not isinstance(x, (Vector, str)):
|
|
129
|
+
raise TypeError("Expected Vector or str")
|
|
126
130
|
return dispatch(count_groups, x)
|
|
127
131
|
|
|
128
132
|
@composite
|
|
@@ -131,21 +135,20 @@ def count_unique(x, *, drop_na=False):
|
|
|
131
135
|
Return the amount of unique elements in `x`.
|
|
132
136
|
|
|
133
137
|
If `x` is a string, return a function usable with
|
|
134
|
-
:meth:`.DataFrame.aggregate` that operates
|
|
138
|
+
:meth:`.DataFrame.aggregate` and :meth:`.DataFrame.modify` that operates
|
|
139
|
+
group-wise on column `x`.
|
|
135
140
|
|
|
136
141
|
>>> di.count_unique(di.Vector([1, 2, 2, 3, 3, 3]))
|
|
137
142
|
>>> di.count_unique("x")
|
|
138
143
|
"""
|
|
139
|
-
def count_unique_groups(
|
|
140
|
-
|
|
141
|
-
n = np.diff(starts, append=len(y))
|
|
144
|
+
def count_unique_groups(codes, starts, take):
|
|
145
|
+
n = np.diff(starts, append=len(codes))
|
|
142
146
|
group = np.repeat(np.arange(len(starts)), n)
|
|
143
|
-
codes = value_codes(y)
|
|
144
147
|
m = codes.max(initial=0) + 1
|
|
145
148
|
# Count unique pairs of group and value.
|
|
146
149
|
keys = util.unique_codes(group * m + codes)[0]
|
|
147
150
|
return np.bincount(keys // m, minlength=len(starts))
|
|
148
|
-
return
|
|
151
|
+
return dispatch_codes(count_unique_groups, x, drop_na)
|
|
149
152
|
|
|
150
153
|
def datetime_as_float(x):
|
|
151
154
|
if not (x.is_datetime() or x.is_timedelta()): return x
|
|
@@ -171,6 +174,34 @@ def dispatch(function, x):
|
|
|
171
174
|
return aggregate
|
|
172
175
|
return item(function(x, np.array([0]))[0])
|
|
173
176
|
|
|
177
|
+
def dispatch_codes(function, x, drop_na):
|
|
178
|
+
# Like dispatch, but function takes value codes of x instead of x, starts
|
|
179
|
+
# of their groups and a function returning elements of x at indices of
|
|
180
|
+
# codes. For a column, codes are computed in source order and reordered
|
|
181
|
+
# to group order, which is faster than reordering e.g. strings first.
|
|
182
|
+
# With drop_na, missing values get code -1, hashing only the rest.
|
|
183
|
+
def get_codes(x):
|
|
184
|
+
na = x.is_na() if drop_na else None
|
|
185
|
+
if na is None or not na.any():
|
|
186
|
+
return value_codes(x)
|
|
187
|
+
codes = np.full(len(x), -1, np.int64)
|
|
188
|
+
codes[~na] = value_codes(x[~na])
|
|
189
|
+
return codes
|
|
190
|
+
def call(codes, take, starts):
|
|
191
|
+
valid = codes >= 0
|
|
192
|
+
if valid.all():
|
|
193
|
+
return function(codes, starts, take)
|
|
194
|
+
kept = np.flatnonzero(valid)
|
|
195
|
+
starts = (np.cumsum(valid) - valid)[starts]
|
|
196
|
+
return function(codes[kept], starts, lambda i: take(kept[i]))
|
|
197
|
+
if isinstance(x, str):
|
|
198
|
+
def aggregate(data, starts):
|
|
199
|
+
take = functools.partial(data._peek, x)
|
|
200
|
+
return call(data._map(x, get_codes), take, starts)
|
|
201
|
+
aggregate.group_aware = True
|
|
202
|
+
return aggregate
|
|
203
|
+
return item(call(get_codes(x), x.__getitem__, np.array([0]))[0])
|
|
204
|
+
|
|
174
205
|
def fill_missing(values, found):
|
|
175
206
|
if found.all(): return values
|
|
176
207
|
# Upcast to have missing values, e.g. int to float.
|
|
@@ -183,7 +214,8 @@ def first(x, *, drop_na=False):
|
|
|
183
214
|
Return the first element of `x`.
|
|
184
215
|
|
|
185
216
|
If `x` is a string, return a function usable with
|
|
186
|
-
:meth:`.DataFrame.aggregate` that operates
|
|
217
|
+
:meth:`.DataFrame.aggregate` and :meth:`.DataFrame.modify` that operates
|
|
218
|
+
group-wise on column `x`.
|
|
187
219
|
|
|
188
220
|
>>> di.first(di.Vector([1, 2, 3]))
|
|
189
221
|
>>> di.first("x")
|
|
@@ -214,7 +246,8 @@ def last(x, *, drop_na=False):
|
|
|
214
246
|
Return the last element of `x`.
|
|
215
247
|
|
|
216
248
|
If `x` is a string, return a function usable with
|
|
217
|
-
:meth:`.DataFrame.aggregate` that operates
|
|
249
|
+
:meth:`.DataFrame.aggregate` and :meth:`.DataFrame.modify` that operates
|
|
250
|
+
group-wise on column `x`.
|
|
218
251
|
|
|
219
252
|
>>> di.last(di.Vector([1, 2, 3]))
|
|
220
253
|
>>> di.last("x")
|
|
@@ -227,7 +260,8 @@ def max(x, *, drop_na=True):
|
|
|
227
260
|
Return the maximum of elements in `x`.
|
|
228
261
|
|
|
229
262
|
If `x` is a string, return a function usable with
|
|
230
|
-
:meth:`.DataFrame.aggregate` that operates
|
|
263
|
+
:meth:`.DataFrame.aggregate` and :meth:`.DataFrame.modify` that operates
|
|
264
|
+
group-wise on column `x`.
|
|
231
265
|
|
|
232
266
|
>>> di.max(di.Vector([4, 5, 6]))
|
|
233
267
|
>>> di.max("x")
|
|
@@ -240,9 +274,9 @@ def mean(x, *, weights=None, drop_na=True):
|
|
|
240
274
|
Return the arithmetic mean of `x`, optionally weighted by `weights`.
|
|
241
275
|
|
|
242
276
|
If `x` is a string, return a function usable with
|
|
243
|
-
:meth:`.DataFrame.aggregate` that operates
|
|
244
|
-
weighted by column `weights`, if given. If `x` is
|
|
245
|
-
should be a vector of the same length.
|
|
277
|
+
:meth:`.DataFrame.aggregate` and :meth:`.DataFrame.modify` that operates
|
|
278
|
+
group-wise on column `x`, weighted by column `weights`, if given. If `x` is
|
|
279
|
+
a vector, `weights` should be a vector of the same length.
|
|
246
280
|
|
|
247
281
|
With `drop_na`, rows where either `x` or `weights` is missing are
|
|
248
282
|
dropped. If weights sum to zero, the result is NaN.
|
|
@@ -295,7 +329,8 @@ def median(x, *, drop_na=True):
|
|
|
295
329
|
Return the median of `x`.
|
|
296
330
|
|
|
297
331
|
If `x` is a string, return a function usable with
|
|
298
|
-
:meth:`.DataFrame.aggregate` that operates
|
|
332
|
+
:meth:`.DataFrame.aggregate` and :meth:`.DataFrame.modify` that operates
|
|
333
|
+
group-wise on column `x`.
|
|
299
334
|
|
|
300
335
|
Equivalent to ``numpy.median``, see the NumPy documentation for details:
|
|
301
336
|
https://numpy.org/doc/stable/reference/generated/numpy.median.html
|
|
@@ -331,7 +366,8 @@ def min(x, *, drop_na=True):
|
|
|
331
366
|
Return the minimum of elements in `x`.
|
|
332
367
|
|
|
333
368
|
If `x` is a string, return a function usable with
|
|
334
|
-
:meth:`.DataFrame.aggregate` that operates
|
|
369
|
+
:meth:`.DataFrame.aggregate` and :meth:`.DataFrame.modify` that operates
|
|
370
|
+
group-wise on column `x`.
|
|
335
371
|
|
|
336
372
|
>>> di.min(di.Vector([4, 5, 6]))
|
|
337
373
|
>>> di.min("x")
|
|
@@ -364,18 +400,17 @@ def mode(x, *, drop_na=True):
|
|
|
364
400
|
Return the most common value in `x`, the first one if tied.
|
|
365
401
|
|
|
366
402
|
If `x` is a string, return a function usable with
|
|
367
|
-
:meth:`.DataFrame.aggregate` that operates
|
|
403
|
+
:meth:`.DataFrame.aggregate` and :meth:`.DataFrame.modify` that operates
|
|
404
|
+
group-wise on column `x`.
|
|
368
405
|
|
|
369
406
|
>>> di.mode(di.Vector([1, 2, 2, 3, 3, 3]))
|
|
370
407
|
>>> di.mode("x")
|
|
371
408
|
"""
|
|
372
|
-
def mode_groups(
|
|
373
|
-
|
|
374
|
-
n = np.diff(starts, append=len(y))
|
|
409
|
+
def mode_groups(codes, starts, take):
|
|
410
|
+
n = np.diff(starts, append=len(codes))
|
|
375
411
|
found = n > 0
|
|
376
412
|
if found.any():
|
|
377
413
|
group = np.repeat(np.arange(len(starts)), n)
|
|
378
|
-
codes = value_codes(y)
|
|
379
414
|
m = codes.max() + 1
|
|
380
415
|
keys, first, pairs = util.unique_codes(group * m + codes)
|
|
381
416
|
# Unique pairs of group and value are in order of first appearance
|
|
@@ -388,11 +423,11 @@ def mode(x, *, drop_na=True):
|
|
|
388
423
|
most = np.repeat(most, np.diff(pair_starts, append=len(keys)))
|
|
389
424
|
candidates = np.flatnonzero(count == most)
|
|
390
425
|
chosen = candidates[group_starts(pair_group[candidates])]
|
|
391
|
-
values =
|
|
426
|
+
values = take(first[chosen])
|
|
392
427
|
else:
|
|
393
|
-
values =
|
|
428
|
+
values = take(np.array([], np.int64))
|
|
394
429
|
return fill_missing(values, found)
|
|
395
|
-
return
|
|
430
|
+
return dispatch_codes(mode_groups, x, drop_na)
|
|
396
431
|
|
|
397
432
|
@composite
|
|
398
433
|
def nth(x, index, *, drop_na=False):
|
|
@@ -400,7 +435,8 @@ def nth(x, index, *, drop_na=False):
|
|
|
400
435
|
Return the element of `x` at `index` (zero-based).
|
|
401
436
|
|
|
402
437
|
If `x` is a string, return a function usable with
|
|
403
|
-
:meth:`.DataFrame.aggregate` that operates
|
|
438
|
+
:meth:`.DataFrame.aggregate` and :meth:`.DataFrame.modify` that operates
|
|
439
|
+
group-wise on column `x`.
|
|
404
440
|
|
|
405
441
|
>>> di.nth(di.Vector([1, 2, 3]), 1)
|
|
406
442
|
>>> di.nth("x", 1)
|
|
@@ -429,7 +465,8 @@ def prod(x, *, drop_na=True):
|
|
|
429
465
|
Return the product of `x`.
|
|
430
466
|
|
|
431
467
|
If `x` is a string, return a function usable with
|
|
432
|
-
:meth:`.DataFrame.aggregate` that operates
|
|
468
|
+
:meth:`.DataFrame.aggregate` and :meth:`.DataFrame.modify` that operates
|
|
469
|
+
group-wise on column `x`.
|
|
433
470
|
|
|
434
471
|
>>> di.prod(di.Vector([1, 2, 3]))
|
|
435
472
|
>>> di.prod("x")
|
|
@@ -442,7 +479,8 @@ def quantile(x, q, *, drop_na=True):
|
|
|
442
479
|
Return the `qth` quantile of `x`.
|
|
443
480
|
|
|
444
481
|
If `x` is a string, return a function usable with
|
|
445
|
-
:meth:`.DataFrame.aggregate` that operates
|
|
482
|
+
:meth:`.DataFrame.aggregate` and :meth:`.DataFrame.modify` that operates
|
|
483
|
+
group-wise on column `x`.
|
|
446
484
|
|
|
447
485
|
Equivalent to ``numpy.quantile``, see the NumPy documentation for details:
|
|
448
486
|
https://numpy.org/doc/stable/reference/generated/numpy.quantile.html
|
|
@@ -502,7 +540,8 @@ def std(x, *, ddof=0, drop_na=True):
|
|
|
502
540
|
Return the standard deviation of `x`.
|
|
503
541
|
|
|
504
542
|
If `x` is a string, return a function usable with
|
|
505
|
-
:meth:`.DataFrame.aggregate` that operates
|
|
543
|
+
:meth:`.DataFrame.aggregate` and :meth:`.DataFrame.modify` that operates
|
|
544
|
+
group-wise on column `x`.
|
|
506
545
|
|
|
507
546
|
Equivalent to ``numpy.std``, see the NumPy documentation for details:
|
|
508
547
|
https://numpy.org/doc/stable/reference/generated/numpy.std.html
|
|
@@ -526,7 +565,8 @@ def sum(x, *, drop_na=True):
|
|
|
526
565
|
Return the sum of `x`.
|
|
527
566
|
|
|
528
567
|
If `x` is a string, return a function usable with
|
|
529
|
-
:meth:`.DataFrame.aggregate` that operates
|
|
568
|
+
:meth:`.DataFrame.aggregate` and :meth:`.DataFrame.modify` that operates
|
|
569
|
+
group-wise on column `x`.
|
|
530
570
|
|
|
531
571
|
>>> di.sum(di.Vector([1, 2, 3]))
|
|
532
572
|
>>> di.sum("x")
|
|
@@ -562,7 +602,8 @@ def var(x, *, ddof=0, drop_na=True):
|
|
|
562
602
|
Return the variance of `x`.
|
|
563
603
|
|
|
564
604
|
If `x` is a string, return a function usable with
|
|
565
|
-
:meth:`.DataFrame.aggregate` that operates
|
|
605
|
+
:meth:`.DataFrame.aggregate` and :meth:`.DataFrame.modify` that operates
|
|
606
|
+
group-wise on column `x`.
|
|
566
607
|
|
|
567
608
|
Equivalent to ``numpy.var``, see the NumPy documentation for details:
|
|
568
609
|
https://numpy.org/doc/stable/reference/generated/numpy.var.html
|