py2ls 0.1.8.4__py3-none-any.whl → 0.1.8.6__py3-none-any.whl
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.
py2ls/plot.py
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import matplotlib.pyplot as plt
|
2
2
|
import numpy as np
|
3
|
+
import pandas as pd
|
3
4
|
from matplotlib.colors import to_rgba
|
4
5
|
from scipy.stats import gaussian_kde
|
5
6
|
|
@@ -318,6 +319,50 @@ def catplot(data, *args, **kwargs):
|
|
318
319
|
# custom_order = ['s', 'bx', 'e']
|
319
320
|
# full_order = sort_catplot_layers(custom_order)
|
320
321
|
|
322
|
+
# figsets
|
323
|
+
kw_figsets = kwargs.get("figsets", None)
|
324
|
+
# check the data type
|
325
|
+
if isinstance(data, pd.DataFrame):
|
326
|
+
df = data.copy()
|
327
|
+
x = kwargs.get("x", None)
|
328
|
+
y = kwargs.get("y", None)
|
329
|
+
hue = kwargs.get("hue", None)
|
330
|
+
data = df2array(data=data, x=x, y=y, hue=hue).T
|
331
|
+
xticklabels = []
|
332
|
+
if hue is not None:
|
333
|
+
for i in df[x].unique().tolist():
|
334
|
+
for j in df[hue].unique().tolist():
|
335
|
+
xticklabels.append(i + "-" + j)
|
336
|
+
x_len = len(df[x].unique().tolist())
|
337
|
+
hue_len = len(df[hue].unique().tolist())
|
338
|
+
xticks = generate_xticks_with_gap(x_len, hue_len)
|
339
|
+
default_x_width = 0.85
|
340
|
+
else:
|
341
|
+
for i in df[x].unique().tolist():
|
342
|
+
xticklabels.append(i)
|
343
|
+
xticks = np.arange(1, len(xticklabels) + 1)
|
344
|
+
default_x_width = 0.5
|
345
|
+
# when the xticklabels are too long, rotate the labels a bit
|
346
|
+
|
347
|
+
xangle = 30 if max([len(i) for i in xticklabels]) > 5 else 0
|
348
|
+
if kw_figsets is not None:
|
349
|
+
kw_figsets = {
|
350
|
+
"ylabel": y,
|
351
|
+
"xlabel": x,
|
352
|
+
"xticks": xticks,
|
353
|
+
"xticklabels": xticklabels,
|
354
|
+
"xangle": xangle,
|
355
|
+
**kw_figsets,
|
356
|
+
}
|
357
|
+
else:
|
358
|
+
kw_figsets = {
|
359
|
+
"ylabel": y,
|
360
|
+
"xlabel": x,
|
361
|
+
"xticks": xticks,
|
362
|
+
"xticklabels": xticklabels,
|
363
|
+
"xangle": xangle,
|
364
|
+
}
|
365
|
+
|
321
366
|
# full_order
|
322
367
|
opt = kwargs.get("opt", {})
|
323
368
|
ax = kwargs.get("ax", None)
|
@@ -347,7 +392,7 @@ def catplot(data, *args, **kwargs):
|
|
347
392
|
|
348
393
|
opt.setdefault("loc", {})
|
349
394
|
opt["loc"].setdefault("go", 0)
|
350
|
-
opt["loc"].setdefault("xloc",
|
395
|
+
opt["loc"].setdefault("xloc", xticks)
|
351
396
|
|
352
397
|
# export setting
|
353
398
|
opt.setdefault("export", {})
|
@@ -366,7 +411,7 @@ def catplot(data, *args, **kwargs):
|
|
366
411
|
opt["b"].setdefault("EdgeAlpha", 1)
|
367
412
|
opt["b"].setdefault("LineStyle", "-")
|
368
413
|
opt["b"].setdefault("LineWidth", 0.8)
|
369
|
-
opt["b"].setdefault("x_width",
|
414
|
+
opt["b"].setdefault("x_width", default_x_width)
|
370
415
|
opt["b"].setdefault("ShowBaseLine", "off")
|
371
416
|
opt["b"].setdefault("hatch", None)
|
372
417
|
|
@@ -470,7 +515,10 @@ def catplot(data, *args, **kwargs):
|
|
470
515
|
opt[key].update(kwargs[key])
|
471
516
|
else:
|
472
517
|
opt[key] = kwargs[key]
|
473
|
-
|
518
|
+
if isinstance(opt["loc"]["xloc"], list):
|
519
|
+
xloc = np.array(opt["loc"]["xloc"])
|
520
|
+
else:
|
521
|
+
xloc = opt["loc"]["xloc"]
|
474
522
|
layers = sort_catplot_layers(opt["layer"])
|
475
523
|
for layer in layers:
|
476
524
|
if layer == "b" and opt["b"]["go"]:
|
@@ -485,8 +533,7 @@ def catplot(data, *args, **kwargs):
|
|
485
533
|
plot_violin(data, opt["v"], xloc, ax)
|
486
534
|
elif all([layer == "l", opt["l"]["go"], opt["s"]["go"]]):
|
487
535
|
plot_lines(data, opt["l"], opt["s"], ax)
|
488
|
-
|
489
|
-
kw_figsets = kwargs.get("figsets", None)
|
536
|
+
|
490
537
|
if kw_figsets is not None:
|
491
538
|
figsets(ax=ax, **kw_figsets)
|
492
539
|
return ax
|
@@ -1357,7 +1404,42 @@ def add_colorbar(im, width=None, pad=None, **kwargs):
|
|
1357
1404
|
return fig.colorbar(im, cax=cax, **kwargs) # draw cbar
|
1358
1405
|
|
1359
1406
|
|
1360
|
-
def padcat(*args, fill_value=np.nan, axis=1):
|
1407
|
+
# def padcat(*args, fill_value=np.nan, axis=1):
|
1408
|
+
# """
|
1409
|
+
# Concatenate vectors with padding.
|
1410
|
+
|
1411
|
+
# Parameters:
|
1412
|
+
# *args : variable number of list or 1D arrays
|
1413
|
+
# Input arrays to concatenate.
|
1414
|
+
# fill_value : scalar, optional
|
1415
|
+
# The value to use for padding the shorter lists (default is np.nan).
|
1416
|
+
# axis : int, optional
|
1417
|
+
# The axis along which to concatenate (0 for rows, 1 for columns, default is 0).
|
1418
|
+
|
1419
|
+
# Returns:
|
1420
|
+
# np.ndarray
|
1421
|
+
# A 2D array with the input arrays concatenated along the specified axis, padded with fill_value where necessary.
|
1422
|
+
# """
|
1423
|
+
# if axis == 0:
|
1424
|
+
# # Concatenate along rows
|
1425
|
+
# max_len = max(len(lst) for lst in args)
|
1426
|
+
# result = np.full((len(args), max_len), fill_value)
|
1427
|
+
# for i, lst in enumerate(args):
|
1428
|
+
# result[i, : len(lst)] = lst
|
1429
|
+
# elif axis == 1:
|
1430
|
+
# # Concatenate along columns
|
1431
|
+
# max_len = max(len(lst) for lst in args)
|
1432
|
+
# result = np.full((max_len, len(args)), fill_value)
|
1433
|
+
# for i, lst in enumerate(args):
|
1434
|
+
# result[: len(lst), i] = lst
|
1435
|
+
# else:
|
1436
|
+
# raise ValueError("axis must be 0 or 1")
|
1437
|
+
|
1438
|
+
# return result
|
1439
|
+
import numpy as np
|
1440
|
+
|
1441
|
+
|
1442
|
+
def padcat(*args, fill_value=np.nan, axis=1, order="row"):
|
1361
1443
|
"""
|
1362
1444
|
Concatenate vectors with padding.
|
1363
1445
|
|
@@ -1367,25 +1449,101 @@ def padcat(*args, fill_value=np.nan, axis=1):
|
|
1367
1449
|
fill_value : scalar, optional
|
1368
1450
|
The value to use for padding the shorter lists (default is np.nan).
|
1369
1451
|
axis : int, optional
|
1370
|
-
The axis along which to concatenate (0 for rows, 1 for columns, default is
|
1452
|
+
The axis along which to concatenate (0 for rows, 1 for columns, default is 1).
|
1371
1453
|
|
1372
1454
|
Returns:
|
1373
1455
|
np.ndarray
|
1374
|
-
A 2D array with the input arrays concatenated along the specified axis,
|
1456
|
+
A 2D array with the input arrays concatenated along the specified axis,
|
1457
|
+
padded with fill_value where necessary.
|
1375
1458
|
"""
|
1459
|
+
# Convert all inputs to 1D NumPy arrays
|
1460
|
+
if "ro" in order.lower():
|
1461
|
+
order = "C" # in row
|
1462
|
+
else:
|
1463
|
+
order = "F" # column
|
1464
|
+
arrays = [np.asarray(arg).flatten(order=order) for arg in args]
|
1465
|
+
|
1376
1466
|
if axis == 0:
|
1377
1467
|
# Concatenate along rows
|
1378
|
-
max_len = max(
|
1379
|
-
result = np.full((len(
|
1380
|
-
for i,
|
1381
|
-
result[i, :
|
1468
|
+
max_len = max(arr.size for arr in arrays)
|
1469
|
+
result = np.full((len(arrays), max_len), fill_value)
|
1470
|
+
for i, arr in enumerate(arrays):
|
1471
|
+
result[i, : arr.size] = arr
|
1382
1472
|
elif axis == 1:
|
1383
1473
|
# Concatenate along columns
|
1384
|
-
max_len = max(
|
1385
|
-
result = np.full((max_len, len(
|
1386
|
-
for i,
|
1387
|
-
result[:
|
1474
|
+
max_len = max(arr.size for arr in arrays)
|
1475
|
+
result = np.full((max_len, len(arrays)), fill_value)
|
1476
|
+
for i, arr in enumerate(arrays):
|
1477
|
+
result[: arr.size, i] = arr
|
1388
1478
|
else:
|
1389
1479
|
raise ValueError("axis must be 0 or 1")
|
1390
1480
|
|
1391
1481
|
return result
|
1482
|
+
|
1483
|
+
|
1484
|
+
def sort_rows_move_nan(arr):
|
1485
|
+
# Handle edge cases where all values are NaN
|
1486
|
+
if np.all(np.isnan(arr)):
|
1487
|
+
return arr # Return unchanged if the entire array is NaN
|
1488
|
+
|
1489
|
+
# Replace NaNs with a temporary large value for sorting
|
1490
|
+
temp_value = (
|
1491
|
+
np.nanmax(arr[np.isfinite(arr)]) + 1 if np.any(np.isfinite(arr)) else np.inf
|
1492
|
+
)
|
1493
|
+
arr_no_nan = np.where(np.isnan(arr), temp_value, arr)
|
1494
|
+
|
1495
|
+
# Sort each row
|
1496
|
+
sorted_arr = np.sort(arr_no_nan, axis=1)
|
1497
|
+
|
1498
|
+
# Move NaNs to the end
|
1499
|
+
result_arr = np.where(sorted_arr == temp_value, np.nan, sorted_arr)
|
1500
|
+
|
1501
|
+
# Remove rows that contain only NaNs
|
1502
|
+
clean_arr = result_arr[~np.isnan(result_arr).all(axis=1)]
|
1503
|
+
|
1504
|
+
# Remove columns that contain only NaNs
|
1505
|
+
clean_arr_ = clean_arr[:, ~np.isnan(clean_arr).all(axis=0)]
|
1506
|
+
|
1507
|
+
return clean_arr_
|
1508
|
+
|
1509
|
+
|
1510
|
+
def df2array(data: pd.DataFrame, x, y, hue=None):
|
1511
|
+
if hue is None:
|
1512
|
+
a = []
|
1513
|
+
cat_x = data[x].unique().tolist()
|
1514
|
+
for i, x_ in enumerate(cat_x):
|
1515
|
+
new_ = data.loc[data[x] == x_, y].to_list()
|
1516
|
+
a = padcat(a, new_, axis=0)
|
1517
|
+
return sort_rows_move_nan(a.reshape(2**i, -1))
|
1518
|
+
else:
|
1519
|
+
a = []
|
1520
|
+
cat_x = data[x].unique().tolist()
|
1521
|
+
cat_hue = data[hue].unique().tolist()
|
1522
|
+
for i, x_ in enumerate(cat_x):
|
1523
|
+
for j, hue_ in enumerate(cat_hue):
|
1524
|
+
new_ = data.loc[(data[x] == x_) & (data[hue] == hue_), y].to_list()
|
1525
|
+
a = padcat(a, new_, axis=0)
|
1526
|
+
return sort_rows_move_nan(a.reshape(2 ** ((i + 1) * (j + 1)), -1))
|
1527
|
+
|
1528
|
+
|
1529
|
+
def generate_xticks_with_gap(x_len, hue_len):
|
1530
|
+
"""
|
1531
|
+
Generate a concatenated array based on x_len and hue_len,
|
1532
|
+
and return only the positive numbers.
|
1533
|
+
|
1534
|
+
Parameters:
|
1535
|
+
- x_len: int, number of segments to generate
|
1536
|
+
- hue_len: int, length of each hue
|
1537
|
+
|
1538
|
+
Returns:
|
1539
|
+
- numpy array: Concatenated array containing only positive numbers
|
1540
|
+
"""
|
1541
|
+
|
1542
|
+
arrays = [
|
1543
|
+
np.arange(1, hue_len + 1) + hue_len * (x_len - i) + (x_len - i)
|
1544
|
+
for i in range(max(x_len, hue_len), 0, -1) # i iterates from 3 to 1
|
1545
|
+
]
|
1546
|
+
concatenated_array = np.concatenate(arrays)
|
1547
|
+
positive_array = concatenated_array[concatenated_array > 0]
|
1548
|
+
|
1549
|
+
return positive_array
|
@@ -134,14 +134,14 @@ py2ls/db2ls.py,sha256=MMfFX47aIPIyu7fU9aPvX9lbPRPYOpJ_VXwlnWk-8qo,13615
|
|
134
134
|
py2ls/doc.py,sha256=xN3g1OWfoaGUhikbJ0NqbN5eKy1VZVvWwRlhHMgyVEc,4243
|
135
135
|
py2ls/export_requirements.py,sha256=x2WgUF0jYKz9GfA1MVKN-MdsM-oQ8yUeC6Ua8oCymio,2325
|
136
136
|
py2ls/freqanalysis.py,sha256=F4218VSPbgL5tnngh6xNCYuNnfR-F_QjECUUxrPYZss,32594
|
137
|
-
py2ls/ips.py,sha256=
|
138
|
-
py2ls/netfinder.py,sha256=
|
139
|
-
py2ls/plot.py,sha256=
|
137
|
+
py2ls/ips.py,sha256=6eNvNwaCDj2jyjter7VPL9oEGB2jS4ge9mSgiIrvZfo,100788
|
138
|
+
py2ls/netfinder.py,sha256=OMStrwMAASf1ajlyEfseoaEygo7G5WKBAFRE0LY15Lw,49477
|
139
|
+
py2ls/plot.py,sha256=drlrWMUseSqkaTQHeTygypn39SUiovYuvThLQZ1Df_Y,55682
|
140
140
|
py2ls/setuptools-70.1.0-py3-none-any.whl,sha256=2bi3cUVal8ip86s0SOvgspteEF8SKLukECi-EWmFomc,882588
|
141
141
|
py2ls/sleep_events_detectors.py,sha256=bQA3HJqv5qnYKJJEIhCyhlDtkXQfIzqksnD0YRXso68,52145
|
142
142
|
py2ls/stats.py,sha256=Wd9yCKQ_61QD29WMEgMuEcreFxF91NmlPW65iWT2B5w,39041
|
143
143
|
py2ls/translator.py,sha256=bc5FB-wqC4TtQz9gyCP1mE38HqNRJ_pmuRIgKnAlMzM,30581
|
144
144
|
py2ls/wb_detector.py,sha256=7y6TmBUj9exCZeIgBAJ_9hwuhkDh1x_-yg4dvNY1_GQ,6284
|
145
|
-
py2ls-0.1.8.
|
146
|
-
py2ls-0.1.8.
|
147
|
-
py2ls-0.1.8.
|
145
|
+
py2ls-0.1.8.6.dist-info/METADATA,sha256=CCDGfjYmrUoLuYqvwidE8OkCBWs-EvCa5tviSzKVOjs,20017
|
146
|
+
py2ls-0.1.8.6.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
147
|
+
py2ls-0.1.8.6.dist-info/RECORD,,
|
File without changes
|