py2ls 0.2.4.32__py3-none-any.whl → 0.2.4.33__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/.git/index +0 -0
- py2ls/ips.py +736 -164
- py2ls/netfinder.py +99 -0
- py2ls/ocr.py +140 -126
- py2ls/plot.py +612 -376
- {py2ls-0.2.4.32.dist-info → py2ls-0.2.4.33.dist-info}/METADATA +1 -1
- {py2ls-0.2.4.32.dist-info → py2ls-0.2.4.33.dist-info}/RECORD +8 -8
- {py2ls-0.2.4.32.dist-info → py2ls-0.2.4.33.dist-info}/WHEEL +0 -0
py2ls/plot.py
CHANGED
@@ -22,7 +22,7 @@ from .ips import (
|
|
22
22
|
run_once_within,
|
23
23
|
get_df_format,
|
24
24
|
df_corr,
|
25
|
-
df_scaler
|
25
|
+
df_scaler,
|
26
26
|
)
|
27
27
|
import scipy.stats as scipy_stats
|
28
28
|
from .stats import *
|
@@ -144,6 +144,7 @@ def add_text(ax=None, height_offset=0.5, fmt=".1f", **kwargs):
|
|
144
144
|
**kwargs,
|
145
145
|
)
|
146
146
|
|
147
|
+
|
147
148
|
def pval2str(p):
|
148
149
|
if p > 0.05:
|
149
150
|
txt = ""
|
@@ -155,16 +156,17 @@ def pval2str(p):
|
|
155
156
|
txt = "***"
|
156
157
|
return txt
|
157
158
|
|
159
|
+
|
158
160
|
def heatmap(
|
159
161
|
data,
|
160
162
|
ax=None,
|
161
163
|
kind="corr", #'corr','direct','pivot'
|
162
|
-
method="pearson"
|
164
|
+
method="pearson", # for correlation: ‘pearson’(default), ‘kendall’, ‘spearman’
|
163
165
|
columns="all", # pivot, default: coll numeric columns
|
164
|
-
style=0
|
166
|
+
style=0, # for correlation
|
165
167
|
index=None, # pivot
|
166
168
|
values=None, # pivot
|
167
|
-
fontsize=10,
|
169
|
+
fontsize=10,
|
168
170
|
tri="u",
|
169
171
|
mask=True,
|
170
172
|
k=1,
|
@@ -174,7 +176,7 @@ def heatmap(
|
|
174
176
|
annot=True,
|
175
177
|
cmap="coolwarm",
|
176
178
|
fmt=".2f",
|
177
|
-
show_indicator
|
179
|
+
show_indicator=True, # only for style==1
|
178
180
|
cluster=False,
|
179
181
|
inplace=False,
|
180
182
|
figsize=(10, 8),
|
@@ -309,7 +311,7 @@ def heatmap(
|
|
309
311
|
df_col_cluster,
|
310
312
|
)
|
311
313
|
else:
|
312
|
-
if style==0:
|
314
|
+
if style == 0:
|
313
315
|
# Create a standard heatmap
|
314
316
|
ax = sns.heatmap(
|
315
317
|
data4heatmap,
|
@@ -321,7 +323,7 @@ def heatmap(
|
|
321
323
|
**kwargs, # Pass any additional arguments to sns.heatmap
|
322
324
|
)
|
323
325
|
return ax
|
324
|
-
elif style==1:
|
326
|
+
elif style == 1:
|
325
327
|
if isinstance(cmap, str):
|
326
328
|
cmap = plt.get_cmap(cmap)
|
327
329
|
norm = plt.Normalize(vmin=-1, vmax=1)
|
@@ -332,12 +334,17 @@ def heatmap(
|
|
332
334
|
# 循环绘制气泡图和数值
|
333
335
|
for i in range(len(r_.columns)):
|
334
336
|
for j in range(len(r_.columns)):
|
335
|
-
if (
|
337
|
+
if (
|
338
|
+
(i < j) if "u" in tri.lower() else (j < i)
|
339
|
+
): # 对角线左上部只显示气泡
|
336
340
|
color = cmap(norm(r_.iloc[i, j])) # 根据相关系数获取颜色
|
337
341
|
scatter = ax.scatter(
|
338
|
-
i,
|
342
|
+
i,
|
343
|
+
j,
|
344
|
+
s=np.abs(r_.iloc[i, j]) * size_scale,
|
345
|
+
color=color,
|
339
346
|
# alpha=1,edgecolor=edgecolor,linewidth=linewidth,
|
340
|
-
**kwargs
|
347
|
+
**kwargs,
|
341
348
|
)
|
342
349
|
scatter_handles.append(scatter) # 保存scatter对象用于颜色条
|
343
350
|
# add *** indicators
|
@@ -351,8 +358,12 @@ def heatmap(
|
|
351
358
|
color="k",
|
352
359
|
fontsize=fontsize * 1.3,
|
353
360
|
)
|
354
|
-
elif (
|
355
|
-
|
361
|
+
elif (
|
362
|
+
(i > j) if "u" in tri.lower() else (j > i)
|
363
|
+
): # 对角只显示数值
|
364
|
+
color = cmap(
|
365
|
+
norm(r_.iloc[i, j])
|
366
|
+
) # 数值的颜色同样基于相关系数
|
356
367
|
ax.text(
|
357
368
|
i,
|
358
369
|
j,
|
@@ -365,15 +376,16 @@ def heatmap(
|
|
365
376
|
else: # 对角线部分,显示空白
|
366
377
|
ax.scatter(i, j, s=1, color="white")
|
367
378
|
# 设置坐标轴标签
|
368
|
-
figsets(
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
379
|
+
figsets(
|
380
|
+
xticks=range(len(r_.columns)),
|
381
|
+
xticklabels=r_.columns,
|
382
|
+
xangle=90,
|
383
|
+
fontsize=fontsize,
|
384
|
+
yticks=range(len(r_.columns)),
|
385
|
+
yticklabels=r_.columns,
|
386
|
+
xlim=[-0.5, len(r_.columns) - 0.5],
|
387
|
+
ylim=[-0.5, len(r_.columns) - 0.5],
|
388
|
+
)
|
377
389
|
# 添加颜色条
|
378
390
|
sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
|
379
391
|
sm.set_array([]) # 仅用于显示颜色条
|
@@ -468,7 +480,7 @@ def heatmap(
|
|
468
480
|
)
|
469
481
|
else:
|
470
482
|
# Create a standard heatmap
|
471
|
-
if style==0:
|
483
|
+
if style == 0:
|
472
484
|
ax = sns.heatmap(
|
473
485
|
data4heatmap,
|
474
486
|
ax=ax,
|
@@ -478,42 +490,51 @@ def heatmap(
|
|
478
490
|
**kwargs, # Pass any additional arguments to sns.heatmap
|
479
491
|
)
|
480
492
|
# Return the Axes object for further customization if needed
|
481
|
-
return ax
|
482
|
-
elif style==1:
|
493
|
+
return ax
|
494
|
+
elif style == 1:
|
483
495
|
if isinstance(cmap, str):
|
484
496
|
cmap = plt.get_cmap(cmap)
|
485
497
|
if vmin is None:
|
486
|
-
vmin=np.min(data4heatmap)
|
498
|
+
vmin = np.min(data4heatmap)
|
487
499
|
if vmax is None:
|
488
|
-
vmax=np.max(data4heatmap)
|
500
|
+
vmax = np.max(data4heatmap)
|
489
501
|
norm = plt.Normalize(vmin=vmin, vmax=vmax)
|
490
502
|
|
491
503
|
# 初始化一个空的可绘制对象用于颜色条
|
492
504
|
scatter_handles = []
|
493
|
-
# 循环绘制气泡图和数值
|
494
|
-
print(len(data4heatmap.index),len(data4heatmap.columns))
|
505
|
+
# 循环绘制气泡图和数值
|
506
|
+
print(len(data4heatmap.index), len(data4heatmap.columns))
|
495
507
|
for i in range(len(data4heatmap.index)):
|
496
508
|
for j in range(len(data4heatmap.columns)):
|
497
509
|
color = cmap(norm(data4heatmap.iloc[i, j])) # 根据相关系数获取颜色
|
498
|
-
scatter = ax.scatter(
|
510
|
+
scatter = ax.scatter(
|
511
|
+
j,
|
512
|
+
i,
|
513
|
+
s=np.abs(data4heatmap.iloc[i, j]) * size_scale,
|
514
|
+
color=color,
|
515
|
+
**kwargs,
|
516
|
+
)
|
499
517
|
scatter_handles.append(scatter) # 保存scatter对象用于颜色条
|
500
518
|
|
501
519
|
# 设置坐标轴标签
|
502
|
-
figsets(
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
510
|
-
|
520
|
+
figsets(
|
521
|
+
xticks=range(len(data4heatmap.columns)),
|
522
|
+
xticklabels=data4heatmap.columns,
|
523
|
+
xangle=90,
|
524
|
+
fontsize=fontsize,
|
525
|
+
yticks=range(len(data4heatmap.index)),
|
526
|
+
yticklabels=data4heatmap.index,
|
527
|
+
xlim=[-0.5, len(data4heatmap.columns) - 0.5],
|
528
|
+
ylim=[-0.5, len(data4heatmap.index) - 0.5],
|
529
|
+
)
|
511
530
|
# 添加颜色条
|
512
531
|
sm = plt.cm.ScalarMappable(cmap=cmap, norm=norm)
|
513
532
|
sm.set_array([]) # 仅用于显示颜色条
|
514
|
-
plt.colorbar(
|
515
|
-
|
516
|
-
|
533
|
+
plt.colorbar(
|
534
|
+
sm,
|
535
|
+
ax=ax,
|
536
|
+
# label="Correlation Coefficient"
|
537
|
+
)
|
517
538
|
return ax
|
518
539
|
|
519
540
|
|
@@ -854,9 +875,11 @@ def catplot(data, *args, **kwargs):
|
|
854
875
|
else:
|
855
876
|
bx_opt["EdgeColor"] = bx_opt["EdgeColor"]
|
856
877
|
if not isinstance(bx_opt["FaceColor"], list):
|
857
|
-
bx_opt["FaceColor"]=[bx_opt["FaceColor"]]
|
858
|
-
if len(bxp["boxes"])!= len(bx_opt["FaceColor"]) and (
|
859
|
-
bx_opt["FaceColor"]
|
878
|
+
bx_opt["FaceColor"] = [bx_opt["FaceColor"]]
|
879
|
+
if len(bxp["boxes"]) != len(bx_opt["FaceColor"]) and (
|
880
|
+
len(bx_opt["FaceColor"]) == 1
|
881
|
+
):
|
882
|
+
bx_opt["FaceColor"] = bx_opt["FaceColor"] * len(bxp["boxes"])
|
860
883
|
for patch, color in zip(bxp["boxes"], bx_opt["FaceColor"]):
|
861
884
|
patch.set_facecolor(to_rgba(color, bx_opt["FaceAlpha"]))
|
862
885
|
|
@@ -2439,7 +2462,15 @@ def split_legend(ax, n=2, loc=None, title=None, bbox=None, ncol=1, **kwargs):
|
|
2439
2462
|
return legends
|
2440
2463
|
|
2441
2464
|
|
2442
|
-
def get_colors(
|
2465
|
+
def get_colors(
|
2466
|
+
n: int = 1,
|
2467
|
+
cmap: str = "auto",
|
2468
|
+
by: str = "start",
|
2469
|
+
alpha: float = 1.0,
|
2470
|
+
output: str = "hue",
|
2471
|
+
*args,
|
2472
|
+
**kwargs,
|
2473
|
+
):
|
2443
2474
|
return get_color(n=n, cmap=cmap, alpha=alpha, output=output, *args, **kwargs)
|
2444
2475
|
|
2445
2476
|
|
@@ -3317,9 +3348,9 @@ def plotxy(
|
|
3317
3348
|
for k in kind_:
|
3318
3349
|
# preprocess data
|
3319
3350
|
try:
|
3320
|
-
data=df_preprocessing_(data, kind=k)
|
3321
|
-
if
|
3322
|
-
x,y=
|
3351
|
+
data = df_preprocessing_(data, kind=k)
|
3352
|
+
if "variable" in data.columns and "value" in data.columns:
|
3353
|
+
x, y = "variable", "value"
|
3323
3354
|
except Exception as e:
|
3324
3355
|
print(e)
|
3325
3356
|
zorder += 1
|
@@ -3342,28 +3373,31 @@ def plotxy(
|
|
3342
3373
|
# (1) return FcetGrid
|
3343
3374
|
if k == "jointplot":
|
3344
3375
|
kws_joint = kwargs.pop("kws_joint", kwargs)
|
3345
|
-
kws_joint = {
|
3346
|
-
k: v for k, v in kws_joint.items() if not k.startswith("kws_")
|
3347
|
-
}
|
3376
|
+
kws_joint = {k: v for k, v in kws_joint.items() if not k.startswith("kws_")}
|
3348
3377
|
hue = kwargs.get("hue", None)
|
3349
|
-
if
|
3378
|
+
if (
|
3379
|
+
isinstance(kws_joint, dict) or hue is None
|
3380
|
+
): # Check if kws_ellipse is a dictionary
|
3350
3381
|
kws_joint.pop("hue", None) # Safely remove 'hue' if it exists
|
3351
3382
|
|
3352
3383
|
palette = kwargs.get("palette", None)
|
3353
3384
|
if palette is None:
|
3354
3385
|
palette = kws_joint.pop(
|
3355
|
-
"palette",
|
3386
|
+
"palette",
|
3387
|
+
get_color(data[hue].nunique()) if hue is not None else None,
|
3356
3388
|
)
|
3357
3389
|
else:
|
3358
3390
|
kws_joint.pop("palette", palette)
|
3359
|
-
stats=kwargs.pop("stats",None)
|
3391
|
+
stats = kwargs.pop("stats", None)
|
3360
3392
|
if stats:
|
3361
|
-
stats=kws_joint.pop("stats",True)
|
3393
|
+
stats = kws_joint.pop("stats", True)
|
3362
3394
|
if stats:
|
3363
3395
|
r, p_value = scipy_stats.pearsonr(data[x], data[y])
|
3364
|
-
for key in ["palette", "alpha", "hue","stats"]:
|
3365
|
-
kws_joint.pop(key, None)
|
3366
|
-
g = sns.jointplot(
|
3396
|
+
for key in ["palette", "alpha", "hue", "stats"]:
|
3397
|
+
kws_joint.pop(key, None)
|
3398
|
+
g = sns.jointplot(
|
3399
|
+
data=data, x=x, y=y, hue=hue, palette=palette, **kws_joint
|
3400
|
+
)
|
3367
3401
|
if stats:
|
3368
3402
|
g.ax_joint.annotate(
|
3369
3403
|
f"pearsonr = {r:.2f} p = {p_value:.3f}",
|
@@ -3391,41 +3425,64 @@ def plotxy(
|
|
3391
3425
|
# If no hue, col, or row, calculate stats for the entire dataset
|
3392
3426
|
if all([hue is None, col is None, row is None]):
|
3393
3427
|
r, p_value = scipy_stats.pearsonr(data[x], data[y])
|
3394
|
-
stats_per_facet[(None, None)] = (
|
3428
|
+
stats_per_facet[(None, None)] = (
|
3429
|
+
r,
|
3430
|
+
p_value,
|
3431
|
+
) # Store stats for the entire dataset
|
3395
3432
|
|
3396
|
-
else:
|
3433
|
+
else:
|
3397
3434
|
if hue is None and (col is not None or row is not None):
|
3398
3435
|
for ax in g.axes.flat:
|
3399
3436
|
facet_name = ax.get_title()
|
3400
|
-
if
|
3437
|
+
if "=" in facet_name:
|
3401
3438
|
# Assume facet_name is like 'Column = Value'
|
3402
|
-
facet_column_name = facet_name.split(
|
3403
|
-
|
3404
|
-
|
3439
|
+
facet_column_name = facet_name.split("=")[
|
3440
|
+
0
|
3441
|
+
].strip() # Column name before '='
|
3442
|
+
facet_value_str = facet_name.split("=")[
|
3443
|
+
1
|
3444
|
+
].strip() # Facet value after '='
|
3445
|
+
|
3405
3446
|
# Try converting facet_value to match the data type of the DataFrame column
|
3406
3447
|
facet_column_dtype = data[facet_column_name].dtype
|
3407
|
-
if
|
3408
|
-
|
3448
|
+
if (
|
3449
|
+
facet_column_dtype == "int"
|
3450
|
+
or facet_column_dtype == "float"
|
3451
|
+
):
|
3452
|
+
facet_value = pd.to_numeric(
|
3453
|
+
facet_value_str, errors="coerce"
|
3454
|
+
) # Convert to numeric
|
3409
3455
|
else:
|
3410
3456
|
facet_value = facet_value_str # Treat as a string if not numeric
|
3411
3457
|
else:
|
3412
|
-
facet_column_name = facet_name.split(
|
3413
|
-
|
3458
|
+
facet_column_name = facet_name.split("=")[
|
3459
|
+
0
|
3460
|
+
].strip() # Column name before '='
|
3461
|
+
facet_value = facet_name.split("=")[1].strip()
|
3414
3462
|
facet_data = data[data[facet_column_name] == facet_value]
|
3415
3463
|
if not facet_data.empty:
|
3416
|
-
r, p_value = scipy_stats.pearsonr(
|
3464
|
+
r, p_value = scipy_stats.pearsonr(
|
3465
|
+
facet_data[x], facet_data[y]
|
3466
|
+
)
|
3417
3467
|
stats_per_facet[facet_name] = (r, p_value)
|
3418
3468
|
else:
|
3419
|
-
stats_per_facet[facet_name] = (
|
3469
|
+
stats_per_facet[facet_name] = (
|
3470
|
+
None,
|
3471
|
+
None,
|
3472
|
+
) # Handle empty facets
|
3420
3473
|
|
3421
3474
|
# Annotate the stats on the plot
|
3422
3475
|
for ax in g.axes.flat:
|
3423
3476
|
if stats:
|
3424
3477
|
# Adjust the position for each facet to avoid overlap
|
3425
|
-
idx=1
|
3426
|
-
shift_factor =
|
3427
|
-
|
3428
|
-
|
3478
|
+
idx = 1
|
3479
|
+
shift_factor = (
|
3480
|
+
0.02 * idx
|
3481
|
+
) # Adjust this factor as needed to prevent overlap
|
3482
|
+
y_position = (
|
3483
|
+
0.98 - shift_factor
|
3484
|
+
) # Dynamic vertical shift for each facet
|
3485
|
+
|
3429
3486
|
if all([hue is None, col is None, row is None]):
|
3430
3487
|
# Use stats for the entire dataset if no hue, col, or row
|
3431
3488
|
r, p_value = stats_per_facet.get((None, None), (None, None))
|
@@ -3448,15 +3505,21 @@ def plotxy(
|
|
3448
3505
|
ha="center",
|
3449
3506
|
)
|
3450
3507
|
elif hue is not None:
|
3451
|
-
if
|
3452
|
-
hue_categories = sorted(flatten(data[hue],verbose=0))
|
3453
|
-
idx=1
|
3508
|
+
if col is None and row is None:
|
3509
|
+
hue_categories = sorted(flatten(data[hue], verbose=0))
|
3510
|
+
idx = 1
|
3454
3511
|
for category in hue_categories:
|
3455
3512
|
subset_data = data[data[hue] == category]
|
3456
|
-
r, p_value = scipy_stats.pearsonr(
|
3513
|
+
r, p_value = scipy_stats.pearsonr(
|
3514
|
+
subset_data[x], subset_data[y]
|
3515
|
+
)
|
3457
3516
|
stats_per_hue[category] = (r, p_value)
|
3458
|
-
shift_factor =
|
3459
|
-
|
3517
|
+
shift_factor = (
|
3518
|
+
0.05 * idx
|
3519
|
+
) # Adjust this factor as needed to prevent overlap
|
3520
|
+
y_position = (
|
3521
|
+
0.98 - shift_factor
|
3522
|
+
) # Dynamic vertical shift for each facet
|
3460
3523
|
ax.annotate(
|
3461
3524
|
f"{category}: pearsonr = {r:.2f} p = {p_value:.3f}",
|
3462
3525
|
xy=(0.6, y_position),
|
@@ -3465,31 +3528,49 @@ def plotxy(
|
|
3465
3528
|
color="black",
|
3466
3529
|
ha="center",
|
3467
3530
|
)
|
3468
|
-
idx+=1
|
3531
|
+
idx += 1
|
3469
3532
|
else:
|
3470
3533
|
for ax in g.axes.flat:
|
3471
3534
|
facet_name = ax.get_title()
|
3472
|
-
if
|
3535
|
+
if "=" in facet_name:
|
3473
3536
|
# Assume facet_name is like 'Column = Value'
|
3474
|
-
facet_column_name = facet_name.split(
|
3475
|
-
|
3476
|
-
|
3537
|
+
facet_column_name = facet_name.split("=")[
|
3538
|
+
0
|
3539
|
+
].strip() # Column name before '='
|
3540
|
+
facet_value_str = facet_name.split("=")[
|
3541
|
+
1
|
3542
|
+
].strip() # Facet value after '='
|
3543
|
+
|
3477
3544
|
# Try converting facet_value to match the data type of the DataFrame column
|
3478
3545
|
facet_column_dtype = data[facet_column_name].dtype
|
3479
|
-
if
|
3480
|
-
|
3546
|
+
if (
|
3547
|
+
facet_column_dtype == "int"
|
3548
|
+
or facet_column_dtype == "float"
|
3549
|
+
):
|
3550
|
+
facet_value = pd.to_numeric(
|
3551
|
+
facet_value_str, errors="coerce"
|
3552
|
+
) # Convert to numeric
|
3481
3553
|
else:
|
3482
3554
|
facet_value = facet_value_str # Treat as a string if not numeric
|
3483
3555
|
else:
|
3484
|
-
facet_column_name = facet_name.split(
|
3485
|
-
|
3486
|
-
|
3556
|
+
facet_column_name = facet_name.split("=")[
|
3557
|
+
0
|
3558
|
+
].strip() # Column name before '='
|
3559
|
+
facet_value = facet_name.split("=")[1].strip()
|
3560
|
+
facet_data = data[
|
3561
|
+
data[facet_column_name] == facet_value
|
3562
|
+
]
|
3487
3563
|
if not facet_data.empty:
|
3488
|
-
r, p_value = scipy_stats.pearsonr(
|
3564
|
+
r, p_value = scipy_stats.pearsonr(
|
3565
|
+
facet_data[x], facet_data[y]
|
3566
|
+
)
|
3489
3567
|
stats_per_facet[facet_name] = (r, p_value)
|
3490
3568
|
else:
|
3491
|
-
stats_per_facet[facet_name] = (
|
3492
|
-
|
3569
|
+
stats_per_facet[facet_name] = (
|
3570
|
+
None,
|
3571
|
+
None,
|
3572
|
+
) # Handle empty facets
|
3573
|
+
|
3493
3574
|
ax.annotate(
|
3494
3575
|
f"pearsonr = {r:.2f} p = {p_value:.3f}",
|
3495
3576
|
xy=(0.6, y_position),
|
@@ -3497,7 +3578,7 @@ def plotxy(
|
|
3497
3578
|
fontsize=12,
|
3498
3579
|
color="black",
|
3499
3580
|
ha="center",
|
3500
|
-
)
|
3581
|
+
)
|
3501
3582
|
elif hue is None and (col is not None or row is not None):
|
3502
3583
|
# Annotate stats for each facet
|
3503
3584
|
facet_name = ax.get_title()
|
@@ -3518,7 +3599,8 @@ def plotxy(
|
|
3518
3599
|
xycoords="axes fraction",
|
3519
3600
|
fontsize=12,
|
3520
3601
|
color="black",
|
3521
|
-
ha="center"
|
3602
|
+
ha="center",
|
3603
|
+
)
|
3522
3604
|
|
3523
3605
|
elif k == "catplot_sns":
|
3524
3606
|
kws_cat = kwargs.pop("kws_cat", kwargs)
|
@@ -3526,7 +3608,7 @@ def plotxy(
|
|
3526
3608
|
elif k == "displot":
|
3527
3609
|
kws_dis = kwargs.pop("kws_dis", kwargs)
|
3528
3610
|
# displot creates a new figure and returns a FacetGrid
|
3529
|
-
g = sns.displot(data=data, x=x,y=y,
|
3611
|
+
g = sns.displot(data=data, x=x, y=y, **kws_dis)
|
3530
3612
|
|
3531
3613
|
# (2) return axis
|
3532
3614
|
if ax is None:
|
@@ -3537,30 +3619,35 @@ def plotxy(
|
|
3537
3619
|
elif k == "stdshade":
|
3538
3620
|
kws_stdshade = kwargs.pop("kws_stdshade", kwargs)
|
3539
3621
|
ax = stdshade(ax=ax, **kwargs)
|
3540
|
-
elif k=="ellipse":
|
3622
|
+
elif k == "ellipse":
|
3541
3623
|
kws_ellipse = kwargs.pop("kws_ellipse", kwargs)
|
3542
3624
|
kws_ellipse = {
|
3543
3625
|
k: v for k, v in kws_ellipse.items() if not k.startswith("kws_")
|
3544
3626
|
}
|
3545
3627
|
hue = kwargs.get("hue", None)
|
3546
|
-
if
|
3628
|
+
if (
|
3629
|
+
isinstance(kws_ellipse, dict) or hue is None
|
3630
|
+
): # Check if kws_ellipse is a dictionary
|
3547
3631
|
kws_ellipse.pop("hue", None) # Safely remove 'hue' if it exists
|
3548
3632
|
|
3549
3633
|
palette = kwargs.get("palette", None)
|
3550
3634
|
if palette is None:
|
3551
3635
|
palette = kws_ellipse.pop(
|
3552
|
-
"palette",
|
3636
|
+
"palette",
|
3637
|
+
get_color(data[hue].nunique()) if hue is not None else None,
|
3553
3638
|
)
|
3554
3639
|
alpha = kws_ellipse.pop("alpha", 0.1)
|
3555
|
-
hue_order = kwargs.get("hue_order",None)
|
3640
|
+
hue_order = kwargs.get("hue_order", None)
|
3556
3641
|
if hue_order is None:
|
3557
|
-
hue_order = kws_ellipse.get("hue_order",None)
|
3558
|
-
if hue_order:
|
3559
|
-
data["hue"] = pd.Categorical(
|
3642
|
+
hue_order = kws_ellipse.get("hue_order", None)
|
3643
|
+
if hue_order:
|
3644
|
+
data["hue"] = pd.Categorical(
|
3645
|
+
data[hue], categories=hue_order, ordered=True
|
3646
|
+
)
|
3560
3647
|
data = data.sort_values(by="hue")
|
3561
|
-
for key in ["palette", "alpha", "hue","hue_order"]:
|
3562
|
-
kws_ellipse.pop(key, None)
|
3563
|
-
ax=ellipse(
|
3648
|
+
for key in ["palette", "alpha", "hue", "hue_order"]:
|
3649
|
+
kws_ellipse.pop(key, None)
|
3650
|
+
ax = ellipse(
|
3564
3651
|
ax=ax,
|
3565
3652
|
data=data,
|
3566
3653
|
x=x,
|
@@ -3579,13 +3666,14 @@ def plotxy(
|
|
3579
3666
|
hue = kwargs.get("hue", None)
|
3580
3667
|
if isinstance(kws_scatter, dict): # Check if kws_scatter is a dictionary
|
3581
3668
|
kws_scatter.pop("hue", None) # Safely remove 'hue' if it exists
|
3582
|
-
palette=kws_scatter.get("palette",None)
|
3669
|
+
palette = kws_scatter.get("palette", None)
|
3583
3670
|
if palette is None:
|
3584
3671
|
palette = kws_scatter.pop(
|
3585
|
-
"palette",
|
3672
|
+
"palette",
|
3673
|
+
get_color(data[hue].nunique()) if hue is not None else None,
|
3586
3674
|
)
|
3587
3675
|
s = kws_scatter.pop("s", 10)
|
3588
|
-
alpha = kws_scatter.pop("alpha", 0.7)
|
3676
|
+
alpha = kws_scatter.pop("alpha", 0.7)
|
3589
3677
|
for key in ["s", "palette", "alpha", "hue"]:
|
3590
3678
|
kws_scatter.pop(key, None)
|
3591
3679
|
|
@@ -3605,28 +3693,39 @@ def plotxy(
|
|
3605
3693
|
kws_hist = kwargs.pop("kws_hist", kwargs)
|
3606
3694
|
kws_hist = {k: v for k, v in kws_hist.items() if not k.startswith("kws_")}
|
3607
3695
|
ax = sns.histplot(data=data, x=x, y=y, ax=ax, zorder=zorder, **kws_hist)
|
3608
|
-
elif k == "kdeplot":
|
3696
|
+
elif k == "kdeplot":
|
3609
3697
|
kws_kde = kwargs.pop("kws_kde", kwargs)
|
3610
|
-
kws_kde = {
|
3611
|
-
k: v for k, v in kws_kde.items() if not k.startswith("kws_")
|
3612
|
-
}
|
3698
|
+
kws_kde = {k: v for k, v in kws_kde.items() if not k.startswith("kws_")}
|
3613
3699
|
hue = kwargs.get("hue", None)
|
3614
|
-
if
|
3700
|
+
if (
|
3701
|
+
isinstance(kws_kde, dict) or hue is None
|
3702
|
+
): # Check if kws_kde is a dictionary
|
3615
3703
|
kws_kde.pop("hue", None) # Safely remove 'hue' if it exists
|
3616
3704
|
|
3617
3705
|
palette = kwargs.get("palette", None)
|
3618
3706
|
if palette is None:
|
3619
3707
|
palette = kws_kde.pop(
|
3620
|
-
"palette",
|
3708
|
+
"palette",
|
3709
|
+
get_color(data[hue].nunique()) if hue is not None else None,
|
3621
3710
|
)
|
3622
3711
|
alpha = kws_kde.pop("alpha", 0.05)
|
3623
3712
|
for key in ["palette", "alpha", "hue"]:
|
3624
|
-
kws_kde.pop(key, None)
|
3625
|
-
ax = sns.kdeplot(
|
3713
|
+
kws_kde.pop(key, None)
|
3714
|
+
ax = sns.kdeplot(
|
3715
|
+
data=data,
|
3716
|
+
x=x,
|
3717
|
+
y=y,
|
3718
|
+
palette=palette,
|
3719
|
+
hue=hue,
|
3720
|
+
ax=ax,
|
3721
|
+
alpha=alpha,
|
3722
|
+
zorder=zorder,
|
3723
|
+
**kws_kde,
|
3724
|
+
)
|
3626
3725
|
elif k == "ecdfplot":
|
3627
3726
|
kws_ecdf = kwargs.pop("kws_ecdf", kwargs)
|
3628
3727
|
kws_ecdf = {k: v for k, v in kws_ecdf.items() if not k.startswith("kws_")}
|
3629
|
-
ax = sns.ecdfplot(data=data, x=x,y=y,
|
3728
|
+
ax = sns.ecdfplot(data=data, x=x, y=y, ax=ax, zorder=zorder, **kws_ecdf)
|
3630
3729
|
elif k == "rugplot":
|
3631
3730
|
kws_rug = kwargs.pop("kws_rug", kwargs)
|
3632
3731
|
kws_rug = {k: v for k, v in kws_rug.items() if not k.startswith("kws_")}
|
@@ -3635,7 +3734,9 @@ def plotxy(
|
|
3635
3734
|
kws_strip = kwargs.pop("kws_strip", kwargs)
|
3636
3735
|
kws_strip = {k: v for k, v in kws_strip.items() if not k.startswith("kws_")}
|
3637
3736
|
dodge = kws_strip.pop("dodge", True)
|
3638
|
-
ax = sns.stripplot(
|
3737
|
+
ax = sns.stripplot(
|
3738
|
+
data=data, x=x, y=y, ax=ax, zorder=zorder, dodge=dodge, **kws_strip
|
3739
|
+
)
|
3639
3740
|
elif k == "swarmplot":
|
3640
3741
|
kws_swarm = kwargs.pop("kws_swarm", kwargs)
|
3641
3742
|
kws_swarm = {k: v for k, v in kws_swarm.items() if not k.startswith("kws_")}
|
@@ -3672,21 +3773,21 @@ def plotxy(
|
|
3672
3773
|
kws_reg = kwargs.pop("kws_reg", kwargs)
|
3673
3774
|
kws_reg = {k: v for k, v in kws_reg.items() if not k.startswith("kws_")}
|
3674
3775
|
stats = kwargs.pop("stats", True) # Flag to calculate stats
|
3675
|
-
|
3776
|
+
|
3676
3777
|
# Compute Pearson correlation if stats is True
|
3677
3778
|
if stats:
|
3678
3779
|
r, p_value = scipy_stats.pearsonr(data[x], data[y])
|
3679
|
-
ax = sns.regplot(data=data, x=x, y=y, ax=ax,
|
3680
|
-
|
3780
|
+
ax = sns.regplot(data=data, x=x, y=y, ax=ax, **kws_reg)
|
3781
|
+
|
3681
3782
|
# Annotate the Pearson correlation and p-value
|
3682
3783
|
ax.annotate(
|
3683
|
-
|
3684
|
-
|
3685
|
-
|
3686
|
-
|
3687
|
-
|
3688
|
-
|
3689
|
-
|
3784
|
+
f"pearsonr = {r:.2f} p = {p_value:.3f}",
|
3785
|
+
xy=(0.6, 0.98),
|
3786
|
+
xycoords="axes fraction",
|
3787
|
+
fontsize=12,
|
3788
|
+
color="black",
|
3789
|
+
ha="center",
|
3790
|
+
)
|
3690
3791
|
elif k == "residplot":
|
3691
3792
|
kws_resid = kwargs.pop("kws_resid", kwargs)
|
3692
3793
|
kws_resid = {k: v for k, v in kws_resid.items() if not k.startswith("kws_")}
|
@@ -3711,6 +3812,7 @@ def plotxy(
|
|
3711
3812
|
return g, ax
|
3712
3813
|
return ax
|
3713
3814
|
|
3815
|
+
|
3714
3816
|
def df_preprocessing_(data, kind, verbose=False):
|
3715
3817
|
"""
|
3716
3818
|
Automatically formats data for various seaborn plot types.
|
@@ -3733,10 +3835,10 @@ def df_preprocessing_(data, kind, verbose=False):
|
|
3733
3835
|
"heatmap",
|
3734
3836
|
"pairplot",
|
3735
3837
|
"jointplot", # Typically requires wide format for axis variables
|
3736
|
-
"facetgrid",
|
3737
|
-
"barplot",
|
3738
|
-
"pointplot",
|
3739
|
-
"pivot_table",
|
3838
|
+
"facetgrid", # Used for creating small multiples (can work with wide format)
|
3839
|
+
"barplot", # Can be used with wide format
|
3840
|
+
"pointplot", # Works well with wide format
|
3841
|
+
"pivot_table", # Works with wide format (aggregated data)
|
3740
3842
|
"boxplot",
|
3741
3843
|
"violinplot",
|
3742
3844
|
"stripplot",
|
@@ -3745,23 +3847,23 @@ def df_preprocessing_(data, kind, verbose=False):
|
|
3745
3847
|
"lineplot",
|
3746
3848
|
"scatterplot",
|
3747
3849
|
"relplot",
|
3748
|
-
"barplot",
|
3749
|
-
"boxenplot",
|
3750
|
-
"countplot",
|
3751
|
-
"heatmap",
|
3752
|
-
"lineplot",
|
3753
|
-
"histplot",
|
3754
|
-
"kdeplot",
|
3755
|
-
"ecdfplot",
|
3756
|
-
"scatterplot",
|
3757
|
-
"lineplot",
|
3758
|
-
"area plot",
|
3850
|
+
"barplot", # Can also work with long format (aggregated data in long form)
|
3851
|
+
"boxenplot", # Similar to boxplot, works with long format
|
3852
|
+
"countplot", # Works best with long format (categorical data)
|
3853
|
+
"heatmap", # Can work with long format after reshaping
|
3854
|
+
"lineplot", # Can work with long format (time series, continuous)
|
3855
|
+
"histplot", # Can be used with both wide and long formats
|
3856
|
+
"kdeplot", # Works with both wide and long formats
|
3857
|
+
"ecdfplot", # Works with both formats
|
3858
|
+
"scatterplot", # Can work with both formats depending on data structure
|
3859
|
+
"lineplot", # Can work with both wide and long formats
|
3860
|
+
"area plot", # Can work with both formats, useful for stacked areas
|
3759
3861
|
"violinplot", # Can work with both formats depending on categorical vs continuous data
|
3760
|
-
"ellipse"
|
3862
|
+
"ellipse", # ellipse plot, default confidence=0.95
|
3761
3863
|
],
|
3762
3864
|
)[0]
|
3763
3865
|
|
3764
|
-
wide_kinds = [
|
3866
|
+
wide_kinds = [
|
3765
3867
|
"pairplot",
|
3766
3868
|
]
|
3767
3869
|
|
@@ -3773,26 +3875,26 @@ def df_preprocessing_(data, kind, verbose=False):
|
|
3773
3875
|
# Flexible kinds: distribution plots can use either format
|
3774
3876
|
flexible_kinds = [
|
3775
3877
|
"jointplot", # Typically requires wide format for axis variables
|
3776
|
-
"lineplot",
|
3878
|
+
"lineplot", # Can work with long format (time series, continuous)
|
3777
3879
|
"lineplot",
|
3778
3880
|
"scatterplot",
|
3779
|
-
"barplot",
|
3780
|
-
"boxenplot",
|
3781
|
-
"countplot",
|
3881
|
+
"barplot", # Can also work with long format (aggregated data in long form)
|
3882
|
+
"boxenplot", # Similar to boxplot, works with long format
|
3883
|
+
"countplot", # Works best with long format (categorical data)
|
3782
3884
|
"regplot",
|
3783
3885
|
"violinplot",
|
3784
3886
|
"stripplot",
|
3785
3887
|
"swarmplot",
|
3786
3888
|
"boxplot",
|
3787
|
-
"histplot",
|
3788
|
-
"kdeplot",
|
3789
|
-
"ecdfplot",
|
3790
|
-
"scatterplot",
|
3791
|
-
"lineplot",
|
3792
|
-
"area plot",
|
3889
|
+
"histplot", # Can be used with both wide and long formats
|
3890
|
+
"kdeplot", # Works with both wide and long formats
|
3891
|
+
"ecdfplot", # Works with both formats
|
3892
|
+
"scatterplot", # Can work with both formats depending on data structure
|
3893
|
+
"lineplot", # Can work with both wide and long formats
|
3894
|
+
"area plot", # Can work with both formats, useful for stacked areas
|
3793
3895
|
"violinplot", # Can work with both formats depending on categorical vs continuous data
|
3794
3896
|
"relplot",
|
3795
|
-
"pointplot",
|
3897
|
+
"pointplot", # Works well with wide format
|
3796
3898
|
"ellipse",
|
3797
3899
|
]
|
3798
3900
|
|
@@ -4296,17 +4398,17 @@ def venn(
|
|
4296
4398
|
colors = ["r", "b"] if len(lists) == 2 else ["r", "g", "b"]
|
4297
4399
|
if labels is None:
|
4298
4400
|
if len(lists) == 2:
|
4299
|
-
labels = ["set1", "set2"]
|
4300
|
-
elif len(lists) == 3:
|
4401
|
+
labels = ["set1", "set2"]
|
4402
|
+
elif len(lists) == 3:
|
4301
4403
|
labels = ["set1", "set2", "set3"]
|
4302
|
-
elif len(lists) == 4:
|
4303
|
-
labels = ["set1", "set2", "set3","set4"]
|
4304
|
-
elif len(lists) == 5:
|
4305
|
-
labels = ["set1", "set2", "set3","set4","set55"]
|
4306
|
-
elif len(lists) == 6:
|
4307
|
-
labels = ["set1", "set2", "set3","set4","set5","set6"]
|
4308
|
-
elif len(lists) == 7:
|
4309
|
-
labels = ["set1", "set2", "set3","set4","set5","set6","set7"]
|
4404
|
+
elif len(lists) == 4:
|
4405
|
+
labels = ["set1", "set2", "set3", "set4"]
|
4406
|
+
elif len(lists) == 5:
|
4407
|
+
labels = ["set1", "set2", "set3", "set4", "set55"]
|
4408
|
+
elif len(lists) == 6:
|
4409
|
+
labels = ["set1", "set2", "set3", "set4", "set5", "set6"]
|
4410
|
+
elif len(lists) == 7:
|
4411
|
+
labels = ["set1", "set2", "set3", "set4", "set5", "set6", "set7"]
|
4310
4412
|
if edgecolor is None:
|
4311
4413
|
edgecolor = colors
|
4312
4414
|
colors = [desaturate_color(color, saturation) for color in colors]
|
@@ -4320,10 +4422,11 @@ def venn(
|
|
4320
4422
|
if show_percentages
|
4321
4423
|
else f"{subset_count}"
|
4322
4424
|
)
|
4425
|
+
|
4323
4426
|
if fmt is not None:
|
4324
4427
|
if not fmt.startswith("{"):
|
4325
|
-
fmt="{:" + fmt + "}"
|
4326
|
-
if len(lists) == 2:
|
4428
|
+
fmt = "{:" + fmt + "}"
|
4429
|
+
if len(lists) == 2:
|
4327
4430
|
|
4328
4431
|
from matplotlib_venn import venn2, venn2_circles
|
4329
4432
|
|
@@ -4345,7 +4448,7 @@ def venn(
|
|
4345
4448
|
# v.get_label_by_id('10').set_text(len(set1 - set2))
|
4346
4449
|
# v.get_label_by_id('01').set_text(len(set2 - set1))
|
4347
4450
|
# v.get_label_by_id('11').set_text(len(set1 & set2))
|
4348
|
-
|
4451
|
+
|
4349
4452
|
v.get_label_by_id("10").set_text(
|
4350
4453
|
get_count_and_percentage(universe, len(set1 - set2))
|
4351
4454
|
)
|
@@ -4447,7 +4550,7 @@ def venn(
|
|
4447
4550
|
if "none" in edgecolor or 0 in linewidth:
|
4448
4551
|
patch.set_edgecolor("none")
|
4449
4552
|
return ax
|
4450
|
-
elif len(lists) == 3:
|
4553
|
+
elif len(lists) == 3:
|
4451
4554
|
|
4452
4555
|
from matplotlib_venn import venn3, venn3_circles
|
4453
4556
|
|
@@ -4463,32 +4566,46 @@ def venn(
|
|
4463
4566
|
# Draw the venn diagram
|
4464
4567
|
v = venn3(subsets=lists, set_labels=labels, ax=ax, **kwargs)
|
4465
4568
|
v.get_patch_by_id("100").set_color(colors[0])
|
4466
|
-
v.get_label_by_id("100").set_text(
|
4569
|
+
v.get_label_by_id("100").set_text(
|
4570
|
+
get_count_and_percentage(universe, len(set1 - set2 - set3))
|
4571
|
+
)
|
4467
4572
|
v.get_patch_by_id("010").set_color(colors[1])
|
4468
|
-
v.get_label_by_id("010").set_text(
|
4573
|
+
v.get_label_by_id("010").set_text(
|
4574
|
+
get_count_and_percentage(universe, len(set2 - set1 - set3))
|
4575
|
+
)
|
4469
4576
|
try:
|
4470
4577
|
v.get_patch_by_id("001").set_color(colors[2])
|
4471
|
-
v.get_label_by_id("001").set_text(
|
4578
|
+
v.get_label_by_id("001").set_text(
|
4579
|
+
get_count_and_percentage(universe, len(set3 - set1 - set2))
|
4580
|
+
)
|
4472
4581
|
except Exception as e:
|
4473
4582
|
print(e)
|
4474
4583
|
try:
|
4475
4584
|
v.get_patch_by_id("110").set_color(colorAB)
|
4476
|
-
v.get_label_by_id("110").set_text(
|
4585
|
+
v.get_label_by_id("110").set_text(
|
4586
|
+
get_count_and_percentage(universe, len(set1 & set2 - set3))
|
4587
|
+
)
|
4477
4588
|
except Exception as e:
|
4478
4589
|
print(e)
|
4479
4590
|
try:
|
4480
4591
|
v.get_patch_by_id("101").set_color(colorAC)
|
4481
|
-
v.get_label_by_id("101").set_text(
|
4592
|
+
v.get_label_by_id("101").set_text(
|
4593
|
+
get_count_and_percentage(universe, len(set1 & set3 - set2))
|
4594
|
+
)
|
4482
4595
|
except Exception as e:
|
4483
4596
|
print(e)
|
4484
4597
|
try:
|
4485
4598
|
v.get_patch_by_id("011").set_color(colorBC)
|
4486
|
-
v.get_label_by_id("011").set_text(
|
4599
|
+
v.get_label_by_id("011").set_text(
|
4600
|
+
get_count_and_percentage(universe, len(set2 & set3 - set1))
|
4601
|
+
)
|
4487
4602
|
except Exception as e:
|
4488
4603
|
print(e)
|
4489
4604
|
try:
|
4490
4605
|
v.get_patch_by_id("111").set_color(colorABC)
|
4491
|
-
v.get_label_by_id("111").set_text(
|
4606
|
+
v.get_label_by_id("111").set_text(
|
4607
|
+
get_count_and_percentage(universe, len(set1 & set2 & set3))
|
4608
|
+
)
|
4492
4609
|
except Exception as e:
|
4493
4610
|
print(e)
|
4494
4611
|
|
@@ -4603,26 +4720,24 @@ def venn(
|
|
4603
4720
|
patch.set_edgecolor("none")
|
4604
4721
|
return ax
|
4605
4722
|
|
4606
|
-
|
4607
4723
|
dict_data = {}
|
4608
4724
|
for i_list, list_ in enumerate(lists):
|
4609
|
-
dict_data[labels[i_list]]={*list_}
|
4725
|
+
dict_data[labels[i_list]] = {*list_}
|
4610
4726
|
|
4611
|
-
if 3<len(lists)<6:
|
4727
|
+
if 3 < len(lists) < 6:
|
4612
4728
|
from venn import venn as vn
|
4613
4729
|
|
4614
|
-
legend_loc=kwargs.pop("legend_loc", "upper right")
|
4615
|
-
ax=vn(dict_data,ax=ax,legend_loc=legend_loc
|
4730
|
+
legend_loc = kwargs.pop("legend_loc", "upper right")
|
4731
|
+
ax = vn(dict_data, ax=ax, legend_loc=legend_loc, **kwargs)
|
4616
4732
|
|
4617
4733
|
return ax
|
4618
4734
|
else:
|
4619
4735
|
from venn import pseudovenn
|
4620
|
-
cmap=kwargs.pop("cmap","plasma")
|
4621
|
-
ax=pseudovenn(dict_data, cmap=cmap,ax=ax,**kwargs)
|
4622
|
-
|
4623
|
-
return ax
|
4624
4736
|
|
4737
|
+
cmap = kwargs.pop("cmap", "plasma")
|
4738
|
+
ax = pseudovenn(dict_data, cmap=cmap, ax=ax, **kwargs)
|
4625
4739
|
|
4740
|
+
return ax
|
4626
4741
|
|
4627
4742
|
|
4628
4743
|
#! subplots, support automatic extend new axis
|
@@ -4670,7 +4785,7 @@ def subplot(
|
|
4670
4785
|
col_first_axes = [None] * cols # Track the first axis in each column (for sharex)
|
4671
4786
|
|
4672
4787
|
def expand_ax():
|
4673
|
-
nonlocal rows, grid_spec,cols,row_first_axes,fig,figsize,figsize_recommend
|
4788
|
+
nonlocal rows, grid_spec, cols, row_first_axes, fig, figsize, figsize_recommend
|
4674
4789
|
# fig_height = fig.get_figheight()
|
4675
4790
|
# subplot_height = fig_height / rows
|
4676
4791
|
rows += 1 # Expands by adding a row
|
@@ -4678,10 +4793,11 @@ def subplot(
|
|
4678
4793
|
fig.set_size_inches(figsize)
|
4679
4794
|
grid_spec = GridSpec(rows, cols, figure=fig)
|
4680
4795
|
row_first_axes.append(None)
|
4681
|
-
figsize_recommend=f"Warning: 建议设置 subplot({rows}, {cols})"
|
4796
|
+
figsize_recommend = f"Warning: 建议设置 subplot({rows}, {cols})"
|
4682
4797
|
print(figsize_recommend)
|
4798
|
+
|
4683
4799
|
def nexttile(rowspan=1, colspan=1, **kwargs):
|
4684
|
-
nonlocal rows, cols, occupied, grid_spec,fig,figsize_recommend
|
4800
|
+
nonlocal rows, cols, occupied, grid_spec, fig, figsize_recommend
|
4685
4801
|
for row in range(rows):
|
4686
4802
|
for col in range(cols):
|
4687
4803
|
if all(
|
@@ -4693,7 +4809,7 @@ def subplot(
|
|
4693
4809
|
else:
|
4694
4810
|
continue
|
4695
4811
|
break
|
4696
|
-
|
4812
|
+
|
4697
4813
|
else:
|
4698
4814
|
expand_ax()
|
4699
4815
|
return nexttile(rowspan=rowspan, colspan=colspan, **kwargs)
|
@@ -4715,12 +4831,13 @@ def subplot(
|
|
4715
4831
|
row_first_axes[row] = ax
|
4716
4832
|
if col_first_axes[col] is None:
|
4717
4833
|
col_first_axes[col] = ax
|
4718
|
-
|
4834
|
+
|
4719
4835
|
for r in range(row, row + rowspan):
|
4720
4836
|
for c in range(col, col + colspan):
|
4721
4837
|
occupied.add((r, c))
|
4722
|
-
|
4838
|
+
|
4723
4839
|
return ax
|
4840
|
+
|
4724
4841
|
return nexttile
|
4725
4842
|
|
4726
4843
|
|
@@ -4743,7 +4860,7 @@ def radar(
|
|
4743
4860
|
bg_color="0.8",
|
4744
4861
|
bg_alpha=None,
|
4745
4862
|
grid_interval_ratio=0.2,
|
4746
|
-
show_value=False
|
4863
|
+
show_value=False, # show text for each value
|
4747
4864
|
cmap=None,
|
4748
4865
|
legend_loc="upper right",
|
4749
4866
|
legend_fontsize=10,
|
@@ -4777,9 +4894,9 @@ def radar(
|
|
4777
4894
|
index=["HP", "MP", "ATK", "DEF", "SP.ATK", "SP.DEF", "SPD"],
|
4778
4895
|
columns=["Hero", "Warrior", "Wizard"],
|
4779
4896
|
)
|
4780
|
-
usage 1:
|
4897
|
+
usage 1:
|
4781
4898
|
radar(data=df)
|
4782
|
-
usage 2:
|
4899
|
+
usage 2:
|
4783
4900
|
radar(data=df["Wizard"])
|
4784
4901
|
usage 3:
|
4785
4902
|
radar(data=df, columns="Wizard")
|
@@ -4819,8 +4936,8 @@ def radar(
|
|
4819
4936
|
- sp (int): Padding for the ticks from the plot area.
|
4820
4937
|
- **kwargs: Additional arguments for customization.
|
4821
4938
|
"""
|
4822
|
-
if run_once_within(20,reverse=True) and verbose:
|
4823
|
-
usage_="""usage:
|
4939
|
+
if run_once_within(20, reverse=True) and verbose:
|
4940
|
+
usage_ = """usage:
|
4824
4941
|
radar(
|
4825
4942
|
data: pd.DataFrame, #The data to plot. Each column corresponds to a variable, and each row represents a data point.
|
4826
4943
|
ylim=(0, 100),# ylim (tuple): The limits of the radial axis (y-axis). Default is (0, 100).
|
@@ -4864,20 +4981,20 @@ def radar(
|
|
4864
4981
|
kws_figsets = v_arg
|
4865
4982
|
kwargs.pop(k_arg, None)
|
4866
4983
|
break
|
4867
|
-
if axis==1:
|
4868
|
-
data=data.T
|
4984
|
+
if axis == 1:
|
4985
|
+
data = data.T
|
4869
4986
|
if isinstance(data, dict):
|
4870
4987
|
data = pd.DataFrame(pd.Series(data))
|
4871
4988
|
if ~isinstance(data, pd.DataFrame):
|
4872
|
-
data=pd.DataFrame(data)
|
4989
|
+
data = pd.DataFrame(data)
|
4873
4990
|
if isinstance(data, pd.DataFrame):
|
4874
|
-
data=data.select_dtypes(include=np.number)
|
4875
|
-
if isinstance(columns,str):
|
4876
|
-
columns=[columns]
|
4991
|
+
data = data.select_dtypes(include=np.number)
|
4992
|
+
if isinstance(columns, str):
|
4993
|
+
columns = [columns]
|
4877
4994
|
if columns is None:
|
4878
4995
|
columns = list(data.columns)
|
4879
|
-
data=data[columns]
|
4880
|
-
categories = list(data.index)
|
4996
|
+
data = data[columns]
|
4997
|
+
categories = list(data.index)
|
4881
4998
|
num_vars = len(categories)
|
4882
4999
|
|
4883
5000
|
# Set y-axis limits and grid intervals
|
@@ -4928,7 +5045,9 @@ def radar(
|
|
4928
5045
|
else:
|
4929
5046
|
# * spider style: spider-style grid (straight lines, not circles)
|
4930
5047
|
# Create the spider-style grid (straight lines, not circles)
|
4931
|
-
for i in range(
|
5048
|
+
for i in range(
|
5049
|
+
1, int((vmax - vmin) / ((vmax - vmin) * grid_interval_ratio)) + 1
|
5050
|
+
): # int(vmax * grid_interval_ratio) + 1):
|
4932
5051
|
ax.plot(
|
4933
5052
|
angles + [angles[0]], # Closing the loop
|
4934
5053
|
[i * vmax * grid_interval_ratio] * (num_vars + 1)
|
@@ -4962,8 +5081,8 @@ def radar(
|
|
4962
5081
|
ax.tick_params(axis="y", pad=sp) # move spines outward
|
4963
5082
|
# colors
|
4964
5083
|
if facecolor is not None:
|
4965
|
-
if not isinstance(facecolor,list):
|
4966
|
-
facecolor=[facecolor]
|
5084
|
+
if not isinstance(facecolor, list):
|
5085
|
+
facecolor = [facecolor]
|
4967
5086
|
colors = facecolor
|
4968
5087
|
else:
|
4969
5088
|
colors = (
|
@@ -4987,44 +5106,44 @@ def radar(
|
|
4987
5106
|
)
|
4988
5107
|
ax.fill(angles, values, color=colors[i], alpha=alpha)
|
4989
5108
|
# Add text labels for each value at each angle
|
4990
|
-
labeled_points = set()
|
5109
|
+
labeled_points = set() # 这样同一个点就不会标多次了
|
4991
5110
|
if show_value:
|
4992
5111
|
for angle, value in zip(angles, values):
|
4993
5112
|
if (angle, value) not in labeled_points:
|
4994
5113
|
# offset_radius = value * value_offset
|
4995
5114
|
lim_ = np.max(values)
|
4996
|
-
sep_in = lim_/5
|
4997
|
-
sep_low=sep_in*2
|
4998
|
-
sep_med=sep_in*3
|
4999
|
-
sep_hig=sep_in*4
|
5000
|
-
sep_out=lim_*5
|
5001
|
-
if value<sep_in:
|
5115
|
+
sep_in = lim_ / 5
|
5116
|
+
sep_low = sep_in * 2
|
5117
|
+
sep_med = sep_in * 3
|
5118
|
+
sep_hig = sep_in * 4
|
5119
|
+
sep_out = lim_ * 5
|
5120
|
+
if value < sep_in:
|
5002
5121
|
offset_radius = value * 0.7
|
5003
|
-
elif value<sep_low:
|
5122
|
+
elif value < sep_low:
|
5004
5123
|
offset_radius = value * 0.8
|
5005
|
-
elif sep_low<=value<sep_med:
|
5124
|
+
elif sep_low <= value < sep_med:
|
5006
5125
|
offset_radius = value * 0.85
|
5007
|
-
elif sep_med<=value<sep_hig:
|
5126
|
+
elif sep_med <= value < sep_hig:
|
5008
5127
|
offset_radius = value * 0.9
|
5009
|
-
elif sep_hig<=value<sep_out:
|
5128
|
+
elif sep_hig <= value < sep_out:
|
5010
5129
|
offset_radius = value * 0.93
|
5011
5130
|
else:
|
5012
5131
|
offset_radius = value * 0.98
|
5013
5132
|
ax.text(
|
5014
|
-
angle,
|
5133
|
+
angle,
|
5015
5134
|
offset_radius,
|
5016
|
-
f"{value:{fmt}}",
|
5017
|
-
ha="center",
|
5018
|
-
va="center",
|
5019
|
-
fontsize=fontsize,
|
5135
|
+
f"{value:{fmt}}",
|
5136
|
+
ha="center",
|
5137
|
+
va="center",
|
5138
|
+
fontsize=fontsize,
|
5020
5139
|
color=fontcolor,
|
5021
|
-
zorder=11
|
5140
|
+
zorder=11,
|
5022
5141
|
)
|
5023
5142
|
labeled_points.add((angle, value))
|
5024
5143
|
|
5025
5144
|
ax.set_ylim(ylim)
|
5026
5145
|
# Add markers for each data point
|
5027
|
-
for i,
|
5146
|
+
for i, (col, val) in enumerate(data.items()):
|
5028
5147
|
ax.plot(
|
5029
5148
|
angles,
|
5030
5149
|
list(val) + [val[0]], # Close the loop for markers
|
@@ -5055,15 +5174,15 @@ def radar(
|
|
5055
5174
|
|
5056
5175
|
|
5057
5176
|
def pie(
|
5058
|
-
data:pd.Series,
|
5059
|
-
columns:list = None,
|
5177
|
+
data: pd.Series,
|
5178
|
+
columns: list = None,
|
5060
5179
|
facecolor=None,
|
5061
5180
|
explode=[0.1],
|
5062
5181
|
startangle=90,
|
5063
5182
|
shadow=True,
|
5064
5183
|
fontcolor="k",
|
5065
|
-
fmt=".2f",
|
5066
|
-
width=None
|
5184
|
+
fmt=".2f",
|
5185
|
+
width=None, # the center blank
|
5067
5186
|
pctdistance=0.85,
|
5068
5187
|
labeldistance=1.1,
|
5069
5188
|
kws_wedge={},
|
@@ -5077,9 +5196,9 @@ def pie(
|
|
5077
5196
|
edgewidth=1,
|
5078
5197
|
cmap=None,
|
5079
5198
|
show_value=False,
|
5080
|
-
show_label=True
|
5081
|
-
expand_label=(1.2,1.2),
|
5082
|
-
kws_bbox={}
|
5199
|
+
show_label=True, # False: only show the outer layer, if it is None, not show
|
5200
|
+
expand_label=(1.2, 1.2),
|
5201
|
+
kws_bbox={}, # dict(facecolor="none", alpha=0.5, edgecolor="black", boxstyle="round,pad=0.3"), # '{}' to hide
|
5083
5202
|
show_legend=True,
|
5084
5203
|
legend_loc="upper right",
|
5085
5204
|
bbox_to_anchor=[1.4, 1.1],
|
@@ -5087,11 +5206,12 @@ def pie(
|
|
5087
5206
|
rotation_correction=0,
|
5088
5207
|
verbose=True,
|
5089
5208
|
ax=None,
|
5090
|
-
**kwargs
|
5091
|
-
):
|
5209
|
+
**kwargs,
|
5210
|
+
):
|
5092
5211
|
from adjustText import adjust_text
|
5093
|
-
|
5094
|
-
|
5212
|
+
|
5213
|
+
if run_once_within(20, reverse=True) and verbose:
|
5214
|
+
usage_ = """usage:
|
5095
5215
|
pie(
|
5096
5216
|
data:pd.Series,
|
5097
5217
|
columns:list = None,
|
@@ -5190,45 +5310,45 @@ def pie(
|
|
5190
5310
|
if isinstance(data, dict):
|
5191
5311
|
data = pd.DataFrame(pd.Series(data))
|
5192
5312
|
if ~isinstance(data, pd.DataFrame):
|
5193
|
-
data=pd.DataFrame(data)
|
5313
|
+
data = pd.DataFrame(data)
|
5194
5314
|
|
5195
5315
|
if isinstance(data, pd.DataFrame):
|
5196
|
-
data=data.select_dtypes(include=np.number)
|
5197
|
-
if isinstance(columns,str):
|
5198
|
-
columns=[columns]
|
5316
|
+
data = data.select_dtypes(include=np.number)
|
5317
|
+
if isinstance(columns, str):
|
5318
|
+
columns = [columns]
|
5199
5319
|
if columns is None:
|
5200
5320
|
columns = list(data.columns)
|
5201
5321
|
# data=data[columns]
|
5202
5322
|
# columns = list(data.columns)
|
5203
5323
|
# print(columns)
|
5204
5324
|
# 选择部分数据
|
5205
|
-
df=data[columns]
|
5325
|
+
df = data[columns]
|
5206
5326
|
|
5207
5327
|
if not isinstance(explode, list):
|
5208
|
-
explode=[explode]
|
5328
|
+
explode = [explode]
|
5209
5329
|
if explode == [None]:
|
5210
|
-
explode=[0]
|
5330
|
+
explode = [0]
|
5211
5331
|
|
5212
5332
|
if width is None:
|
5213
|
-
if df.shape[1]>1:
|
5214
|
-
width=1/(df.shape[1]+2)
|
5333
|
+
if df.shape[1] > 1:
|
5334
|
+
width = 1 / (df.shape[1] + 2)
|
5215
5335
|
else:
|
5216
|
-
width=1
|
5217
|
-
if isinstance(width,(float,int)):
|
5218
|
-
width=[width]
|
5219
|
-
if len(width)<df.shape[1]:
|
5220
|
-
width=width*df.shape[1]
|
5221
|
-
if isinstance(radius,(float,int)):
|
5222
|
-
radius=[radius]
|
5223
|
-
radius_tile=[1]*df.shape[1]
|
5224
|
-
radius=radius_tile.copy()
|
5225
|
-
for i in range(1,df.shape[1]):
|
5226
|
-
radius[i]=radius_tile[i]-np.sum(width[:i])
|
5336
|
+
width = 1
|
5337
|
+
if isinstance(width, (float, int)):
|
5338
|
+
width = [width]
|
5339
|
+
if len(width) < df.shape[1]:
|
5340
|
+
width = width * df.shape[1]
|
5341
|
+
if isinstance(radius, (float, int)):
|
5342
|
+
radius = [radius]
|
5343
|
+
radius_tile = [1] * df.shape[1]
|
5344
|
+
radius = radius_tile.copy()
|
5345
|
+
for i in range(1, df.shape[1]):
|
5346
|
+
radius[i] = radius_tile[i] - np.sum(width[:i])
|
5227
5347
|
|
5228
5348
|
# colors
|
5229
5349
|
if facecolor is not None:
|
5230
|
-
if not isinstance(facecolor,list):
|
5231
|
-
facecolor=[facecolor]
|
5350
|
+
if not isinstance(facecolor, list):
|
5351
|
+
facecolor = [facecolor]
|
5232
5352
|
colors = facecolor
|
5233
5353
|
else:
|
5234
5354
|
colors = (
|
@@ -5239,38 +5359,38 @@ def pie(
|
|
5239
5359
|
# to check if facecolor is nested list or not
|
5240
5360
|
is_nested = True if any(isinstance(i, list) for i in colors) else False
|
5241
5361
|
inested = 0
|
5242
|
-
for column_,width_,radius_ in zip(columns, width,radius):
|
5243
|
-
if column_!=columns[0]:
|
5362
|
+
for column_, width_, radius_ in zip(columns, width, radius):
|
5363
|
+
if column_ != columns[0]:
|
5244
5364
|
labels = data.index if show_label else None
|
5245
5365
|
else:
|
5246
5366
|
labels = data.index if show_label is not None else None
|
5247
5367
|
data = df[column_]
|
5248
|
-
labels_legend=data.index
|
5368
|
+
labels_legend = data.index
|
5249
5369
|
sizes = data.values
|
5250
|
-
|
5370
|
+
|
5251
5371
|
# Set wedge and text properties if none are provided
|
5252
5372
|
kws_wedge = kws_wedge or {"edgecolor": edgecolor, "linewidth": edgewidth}
|
5253
|
-
kws_wedge.update({"width":width_})
|
5254
|
-
fontcolor=kws_text.get("color",fontcolor)
|
5255
|
-
fontsize=kws_text.get("fontsize",fontsize)
|
5373
|
+
kws_wedge.update({"width": width_})
|
5374
|
+
fontcolor = kws_text.get("color", fontcolor)
|
5375
|
+
fontsize = kws_text.get("fontsize", fontsize)
|
5256
5376
|
kws_text.update({"color": fontcolor, "fontsize": fontsize})
|
5257
5377
|
|
5258
|
-
if ax is None:
|
5259
|
-
ax=plt.gca()
|
5260
|
-
if len(explode)<len(labels_legend):
|
5261
|
-
explode.extend([0]*(len(labels_legend)-len(explode)))
|
5378
|
+
if ax is None:
|
5379
|
+
ax = plt.gca()
|
5380
|
+
if len(explode) < len(labels_legend):
|
5381
|
+
explode.extend([0] * (len(labels_legend) - len(explode)))
|
5262
5382
|
print(explode)
|
5263
5383
|
if fmt:
|
5264
5384
|
if not fmt.startswith("%"):
|
5265
|
-
autopct =f"%{fmt}%%"
|
5385
|
+
autopct = f"%{fmt}%%"
|
5266
5386
|
else:
|
5267
|
-
autopct=None
|
5387
|
+
autopct = None
|
5268
5388
|
|
5269
5389
|
if show_value is None:
|
5270
5390
|
result = ax.pie(
|
5271
5391
|
sizes,
|
5272
5392
|
labels=labels,
|
5273
|
-
autopct=
|
5393
|
+
autopct=None,
|
5274
5394
|
startangle=startangle + rotation_correction,
|
5275
5395
|
explode=explode,
|
5276
5396
|
colors=colors[inested] if is_nested else colors,
|
@@ -5282,7 +5402,7 @@ def pie(
|
|
5282
5402
|
center=center,
|
5283
5403
|
radius=radius_,
|
5284
5404
|
frame=frame,
|
5285
|
-
**kwargs
|
5405
|
+
**kwargs,
|
5286
5406
|
)
|
5287
5407
|
else:
|
5288
5408
|
result = ax.pie(
|
@@ -5292,7 +5412,7 @@ def pie(
|
|
5292
5412
|
startangle=startangle + rotation_correction,
|
5293
5413
|
explode=explode,
|
5294
5414
|
colors=colors[inested] if is_nested else colors,
|
5295
|
-
shadow=shadow
|
5415
|
+
shadow=shadow, # shadow,
|
5296
5416
|
pctdistance=pctdistance,
|
5297
5417
|
labeldistance=labeldistance,
|
5298
5418
|
wedgeprops=kws_wedge,
|
@@ -5300,13 +5420,13 @@ def pie(
|
|
5300
5420
|
center=center,
|
5301
5421
|
radius=radius_,
|
5302
5422
|
frame=frame,
|
5303
|
-
**kwargs
|
5423
|
+
**kwargs,
|
5304
5424
|
)
|
5305
5425
|
if len(result) == 3:
|
5306
5426
|
wedges, texts, autotexts = result
|
5307
5427
|
elif len(result) == 2:
|
5308
5428
|
wedges, texts = result
|
5309
|
-
autotexts = None
|
5429
|
+
autotexts = None
|
5310
5430
|
#! adjust_text
|
5311
5431
|
if autotexts or texts:
|
5312
5432
|
all_texts = []
|
@@ -5314,30 +5434,38 @@ def pie(
|
|
5314
5434
|
all_texts.extend(autotexts)
|
5315
5435
|
if texts and show_label:
|
5316
5436
|
all_texts.extend(texts)
|
5317
|
-
|
5437
|
+
|
5318
5438
|
adjust_text(
|
5319
5439
|
all_texts,
|
5320
5440
|
ax=ax,
|
5321
|
-
arrowprops=kws_arrow
|
5441
|
+
arrowprops=kws_arrow, # dict(arrowstyle="-", color="gray", lw=0.5),
|
5322
5442
|
bbox=kws_bbox if kws_bbox else None,
|
5323
5443
|
expand=expand_label,
|
5324
5444
|
fontdict={
|
5325
|
-
|
5326
|
-
|
5327
|
-
|
5445
|
+
"fontsize": fontsize,
|
5446
|
+
"color": fontcolor,
|
5447
|
+
},
|
5328
5448
|
)
|
5329
5449
|
# Show exact values on wedges if show_value is True
|
5330
5450
|
if show_value:
|
5331
5451
|
for i, (wedge, txt) in enumerate(zip(wedges, texts)):
|
5332
5452
|
angle = (wedge.theta2 - wedge.theta1) / 2 + wedge.theta1
|
5333
|
-
x = np.cos(np.radians(angle)) * (pctdistance
|
5334
|
-
y = np.sin(np.radians(angle)) * (pctdistance
|
5453
|
+
x = np.cos(np.radians(angle)) * (pctdistance) * radius_
|
5454
|
+
y = np.sin(np.radians(angle)) * (pctdistance) * radius_
|
5335
5455
|
if not fmt.startswith("{"):
|
5336
5456
|
value_text = f"{sizes[i]:{fmt}}"
|
5337
5457
|
else:
|
5338
|
-
value_text = fmt.format(sizes[i])
|
5339
|
-
ax.text(
|
5340
|
-
|
5458
|
+
value_text = fmt.format(sizes[i])
|
5459
|
+
ax.text(
|
5460
|
+
x,
|
5461
|
+
y,
|
5462
|
+
value_text,
|
5463
|
+
ha="center",
|
5464
|
+
va="center",
|
5465
|
+
fontsize=fontsize,
|
5466
|
+
color=fontcolor,
|
5467
|
+
)
|
5468
|
+
inested += 1
|
5341
5469
|
# Customize the legend
|
5342
5470
|
if show_legend:
|
5343
5471
|
ax.legend(
|
@@ -5347,10 +5475,11 @@ def pie(
|
|
5347
5475
|
bbox_to_anchor=bbox_to_anchor,
|
5348
5476
|
fontsize=legend_fontsize,
|
5349
5477
|
title_fontsize=legend_fontsize,
|
5350
|
-
)
|
5478
|
+
)
|
5351
5479
|
ax.set(aspect="equal")
|
5352
5480
|
return ax
|
5353
5481
|
|
5482
|
+
|
5354
5483
|
def ellipse(
|
5355
5484
|
data,
|
5356
5485
|
x=None,
|
@@ -5363,7 +5492,7 @@ def ellipse(
|
|
5363
5492
|
palette=None,
|
5364
5493
|
facecolor=None,
|
5365
5494
|
edgecolor=None,
|
5366
|
-
label:bool=True,
|
5495
|
+
label: bool = True,
|
5367
5496
|
**kwargs,
|
5368
5497
|
):
|
5369
5498
|
"""
|
@@ -5438,8 +5567,8 @@ def ellipse(
|
|
5438
5567
|
groups = [None]
|
5439
5568
|
color_map = {None: kwargs.get("edgecolor", "blue")}
|
5440
5569
|
alpha = kwargs.pop("alpha", 0.2)
|
5441
|
-
edgecolor=kwargs.pop("edgecolor", None)
|
5442
|
-
facecolor=kwargs.pop("facecolor", None)
|
5570
|
+
edgecolor = kwargs.pop("edgecolor", None)
|
5571
|
+
facecolor = kwargs.pop("facecolor", None)
|
5443
5572
|
for group in groups:
|
5444
5573
|
group_data = data[data[hue] == group] if hue else data
|
5445
5574
|
|
@@ -5477,7 +5606,7 @@ def ellipse(
|
|
5477
5606
|
height=height,
|
5478
5607
|
angle=angle,
|
5479
5608
|
edgecolor=edgecolor_,
|
5480
|
-
facecolor=(facecolor_, alpha),
|
5609
|
+
facecolor=(facecolor_, alpha), # facecolor_, # only work on facecolor
|
5481
5610
|
# alpha=alpha,
|
5482
5611
|
label=group if (hue and label) else None,
|
5483
5612
|
**kwargs,
|
@@ -5504,6 +5633,7 @@ def ellipse(
|
|
5504
5633
|
|
5505
5634
|
return ax
|
5506
5635
|
|
5636
|
+
|
5507
5637
|
def ppi(
|
5508
5638
|
interactions,
|
5509
5639
|
player1="preferredName_A",
|
@@ -5511,39 +5641,39 @@ def ppi(
|
|
5511
5641
|
weight="score",
|
5512
5642
|
n_layers=None, # Number of concentric layers
|
5513
5643
|
n_rank=[5, 10], # Nodes in each rank for the concentric layout
|
5514
|
-
dist_node
|
5515
|
-
layout="degree",
|
5516
|
-
size=None
|
5517
|
-
sizes=(50,500)
|
5644
|
+
dist_node=10, # Distance between each rank of circles
|
5645
|
+
layout="degree",
|
5646
|
+
size=None, # 700,
|
5647
|
+
sizes=(50, 500), # min and max of size
|
5518
5648
|
facecolor="skyblue",
|
5519
|
-
cmap=
|
5649
|
+
cmap="coolwarm",
|
5520
5650
|
edgecolor="k",
|
5521
5651
|
edgelinewidth=1.5,
|
5522
|
-
alpha
|
5523
|
-
alphas=(0.1, 1.0)
|
5652
|
+
alpha=0.5,
|
5653
|
+
alphas=(0.1, 1.0), # min and max of alpha
|
5524
5654
|
marker="o",
|
5525
5655
|
node_hideticks=True,
|
5526
5656
|
linecolor="gray",
|
5527
|
-
line_cmap=
|
5657
|
+
line_cmap="coolwarm",
|
5528
5658
|
linewidth=1.5,
|
5529
|
-
linewidths=(0.5,5)
|
5659
|
+
linewidths=(0.5, 5), # min and max of linewidth
|
5530
5660
|
linealpha=1.0,
|
5531
|
-
linealphas=(0.1,1.0)
|
5661
|
+
linealphas=(0.1, 1.0), # min and max of linealpha
|
5532
5662
|
linestyle="-",
|
5533
|
-
line_arrowstyle=
|
5663
|
+
line_arrowstyle="-",
|
5534
5664
|
fontsize=10,
|
5535
5665
|
fontcolor="k",
|
5536
|
-
ha:str="center",
|
5537
|
-
va:str="center",
|
5666
|
+
ha: str = "center",
|
5667
|
+
va: str = "center",
|
5538
5668
|
figsize=(12, 10),
|
5539
|
-
k_value=0.3,
|
5669
|
+
k_value=0.3,
|
5540
5670
|
bgcolor="w",
|
5541
5671
|
dir_save="./ppi_network.html",
|
5542
5672
|
physics=True,
|
5543
5673
|
notebook=False,
|
5544
5674
|
scale=1,
|
5545
5675
|
ax=None,
|
5546
|
-
**kwargs
|
5676
|
+
**kwargs,
|
5547
5677
|
):
|
5548
5678
|
"""
|
5549
5679
|
Plot a Protein-Protein Interaction (PPI) network with adjustable appearance.
|
@@ -5560,14 +5690,14 @@ def ppi(
|
|
5560
5690
|
)
|
5561
5691
|
"""
|
5562
5692
|
from pyvis.network import Network
|
5563
|
-
import networkx as nx
|
5693
|
+
import networkx as nx
|
5564
5694
|
from IPython.display import IFrame
|
5565
5695
|
from matplotlib.colors import Normalize
|
5566
5696
|
from matplotlib import cm
|
5567
5697
|
from . import ips
|
5568
5698
|
|
5569
5699
|
if run_once_within():
|
5570
|
-
usage_str="""
|
5700
|
+
usage_str = """
|
5571
5701
|
ppi(
|
5572
5702
|
interactions,
|
5573
5703
|
player1="preferredName_A",
|
@@ -5611,17 +5741,19 @@ def ppi(
|
|
5611
5741
|
):
|
5612
5742
|
"""
|
5613
5743
|
print(usage_str)
|
5614
|
-
|
5744
|
+
|
5615
5745
|
# Check for required columns in the DataFrame
|
5616
5746
|
for col in [player1, player2, weight]:
|
5617
5747
|
if col not in interactions.columns:
|
5618
|
-
raise ValueError(
|
5748
|
+
raise ValueError(
|
5749
|
+
f"Column '{col}' is missing from the interactions DataFrame."
|
5750
|
+
)
|
5619
5751
|
interactions.sort_values(by=[weight], inplace=True)
|
5620
5752
|
# Initialize Pyvis network
|
5621
5753
|
net = Network(height="750px", width="100%", bgcolor=bgcolor, font_color=fontcolor)
|
5622
5754
|
net.force_atlas_2based(
|
5623
5755
|
gravity=-50, central_gravity=0.01, spring_length=100, spring_strength=0.1
|
5624
|
-
)
|
5756
|
+
)
|
5625
5757
|
net.toggle_physics(physics)
|
5626
5758
|
|
5627
5759
|
kws_figsets = {}
|
@@ -5637,47 +5769,62 @@ def ppi(
|
|
5637
5769
|
G.add_edge(row[player1], row[player2], weight=row[weight])
|
5638
5770
|
# G = nx.from_pandas_edgelist(interactions, source=player1, target=player2, edge_attr=weight)
|
5639
5771
|
|
5640
|
-
|
5641
5772
|
# Calculate node degrees
|
5642
5773
|
degrees = dict(G.degree())
|
5643
5774
|
norm = Normalize(vmin=min(degrees.values()), vmax=max(degrees.values()))
|
5644
5775
|
colormap = cm.get_cmap(cmap) # Get the 'coolwarm' colormap
|
5645
5776
|
|
5646
|
-
if not ips.isa(facecolor,
|
5777
|
+
if not ips.isa(facecolor, "color"):
|
5647
5778
|
print("facecolor: based on degrees")
|
5648
5779
|
facecolor = [colormap(norm(deg)) for deg in degrees.values()] # Use colormap
|
5649
5780
|
num_nodes = G.number_of_nodes()
|
5650
|
-
|
5781
|
+
# * size
|
5651
5782
|
# Set properties based on degrees
|
5652
|
-
if not isinstance(size, (int,float,list)):
|
5783
|
+
if not isinstance(size, (int, float, list)):
|
5653
5784
|
print("size: based on degrees")
|
5654
5785
|
size = [deg * 50 for deg in degrees.values()] # Scale sizes
|
5655
|
-
size = (
|
5656
|
-
|
5786
|
+
size = (
|
5787
|
+
(size[:num_nodes] if len(size) > num_nodes else size)
|
5788
|
+
if isinstance(size, list)
|
5789
|
+
else [size] * num_nodes
|
5790
|
+
)
|
5791
|
+
if isinstance(size, list) and len(ips.flatten(size, verbose=False)) != 1:
|
5657
5792
|
# Normalize sizes
|
5658
5793
|
min_size, max_size = sizes # Use sizes tuple for min and max values
|
5659
5794
|
min_degree, max_degree = min(size), max(size)
|
5660
5795
|
if max_degree > min_degree: # Avoid division by zero
|
5661
5796
|
size = [
|
5662
|
-
min_size
|
5797
|
+
min_size
|
5798
|
+
+ (max_size - min_size) * (sz - min_degree) / (max_degree - min_degree)
|
5663
5799
|
for sz in size
|
5664
5800
|
]
|
5665
5801
|
else:
|
5666
5802
|
# If all values are the same, set them to a default of the midpoint
|
5667
5803
|
size = [(min_size + max_size) / 2] * len(size)
|
5668
5804
|
|
5669
|
-
|
5670
|
-
facecolor = (
|
5805
|
+
# * facecolor
|
5806
|
+
facecolor = (
|
5807
|
+
(facecolor[:num_nodes] if len(facecolor) > num_nodes else facecolor)
|
5808
|
+
if isinstance(facecolor, list)
|
5809
|
+
else [facecolor] * num_nodes
|
5810
|
+
)
|
5671
5811
|
# * facealpha
|
5672
5812
|
if isinstance(alpha, list):
|
5673
|
-
alpha = (
|
5813
|
+
alpha = (
|
5814
|
+
alpha[:num_nodes]
|
5815
|
+
if len(alpha) > num_nodes
|
5816
|
+
else alpha + [alpha[-1]] * (num_nodes - len(alpha))
|
5817
|
+
)
|
5674
5818
|
min_alphas, max_alphas = alphas # Use alphas tuple for min and max values
|
5675
5819
|
if len(alpha) > 0:
|
5676
5820
|
# Normalize alpha based on the specified min and max
|
5677
5821
|
min_alpha, max_alpha = min(alpha), max(alpha)
|
5678
5822
|
if max_alpha > min_alpha: # Avoid division by zero
|
5679
5823
|
alpha = [
|
5680
|
-
min_alphas
|
5824
|
+
min_alphas
|
5825
|
+
+ (max_alphas - min_alphas)
|
5826
|
+
* (ea - min_alpha)
|
5827
|
+
/ (max_alpha - min_alpha)
|
5681
5828
|
for ea in alpha
|
5682
5829
|
]
|
5683
5830
|
else:
|
@@ -5685,7 +5832,7 @@ def ppi(
|
|
5685
5832
|
alpha = [(min_alphas + max_alphas) / 2] * len(alpha)
|
5686
5833
|
else:
|
5687
5834
|
# Default to a full opacity if no edges are provided
|
5688
|
-
alpha = [1.0] * num_nodes
|
5835
|
+
alpha = [1.0] * num_nodes
|
5689
5836
|
else:
|
5690
5837
|
# If alpha is a single value, convert it to a list and normalize it
|
5691
5838
|
alpha = [alpha] * num_nodes # Adjust based on alphas
|
@@ -5699,7 +5846,7 @@ def ppi(
|
|
5699
5846
|
alpha=alpha[i],
|
5700
5847
|
font={"size": fontsize, "color": fontcolor},
|
5701
5848
|
)
|
5702
|
-
print(f
|
5849
|
+
print(f"nodes number: {i+1}")
|
5703
5850
|
|
5704
5851
|
for edge in G.edges(data=True):
|
5705
5852
|
net.add_edge(
|
@@ -5718,11 +5865,11 @@ def ppi(
|
|
5718
5865
|
"shell",
|
5719
5866
|
"planar",
|
5720
5867
|
"spiral",
|
5721
|
-
"degree"
|
5868
|
+
"degree",
|
5722
5869
|
]
|
5723
5870
|
layout = ips.strcmp(layout, layouts)[0]
|
5724
5871
|
print(f"layout:{layout}, or select one in {layouts}")
|
5725
|
-
|
5872
|
+
|
5726
5873
|
# Choose layout
|
5727
5874
|
if layout == "spring":
|
5728
5875
|
pos = nx.spring_layout(G, k=k_value)
|
@@ -5744,24 +5891,26 @@ def ppi(
|
|
5744
5891
|
pos = nx.spring_layout(G, k=k_value)
|
5745
5892
|
elif layout == "spiral":
|
5746
5893
|
pos = nx.spiral_layout(G)
|
5747
|
-
elif layout==
|
5894
|
+
elif layout == "degree":
|
5748
5895
|
# Calculate node degrees and sort nodes by degree
|
5749
5896
|
degrees = dict(G.degree())
|
5750
5897
|
sorted_nodes = sorted(degrees.items(), key=lambda x: x[1], reverse=True)
|
5751
5898
|
norm = Normalize(vmin=min(degrees.values()), vmax=max(degrees.values()))
|
5752
5899
|
colormap = cm.get_cmap(cmap)
|
5753
|
-
|
5900
|
+
|
5754
5901
|
# Create positions for concentric circles based on n_layers and n_rank
|
5755
5902
|
pos = {}
|
5756
|
-
n_layers=len(n_rank)+1 if n_layers is None else n_layers
|
5903
|
+
n_layers = len(n_rank) + 1 if n_layers is None else n_layers
|
5757
5904
|
for rank_index in range(n_layers):
|
5758
5905
|
if rank_index < len(n_rank):
|
5759
5906
|
nodes_per_rank = n_rank[rank_index]
|
5760
|
-
rank_nodes = sorted_nodes[
|
5907
|
+
rank_nodes = sorted_nodes[
|
5908
|
+
sum(n_rank[:rank_index]) : sum(n_rank[: rank_index + 1])
|
5909
|
+
]
|
5761
5910
|
else:
|
5762
5911
|
# 随机打乱剩余节点的顺序
|
5763
|
-
remaining_nodes = sorted_nodes[sum(n_rank[:rank_index]):]
|
5764
|
-
random_indices = np.random.permutation(len(remaining_nodes))
|
5912
|
+
remaining_nodes = sorted_nodes[sum(n_rank[:rank_index]) :]
|
5913
|
+
random_indices = np.random.permutation(len(remaining_nodes))
|
5765
5914
|
rank_nodes = [remaining_nodes[i] for i in random_indices]
|
5766
5915
|
|
5767
5916
|
radius = (rank_index + 1) * dist_node # Radius for this rank
|
@@ -5772,7 +5921,9 @@ def ppi(
|
|
5772
5921
|
pos[node] = (radius * np.cos(angle), radius * np.sin(angle))
|
5773
5922
|
|
5774
5923
|
else:
|
5775
|
-
print(
|
5924
|
+
print(
|
5925
|
+
f"Unknown layout '{layout}', defaulting to 'spring',or可以用这些: {layouts}"
|
5926
|
+
)
|
5776
5927
|
pos = nx.spring_layout(G, k=k_value)
|
5777
5928
|
|
5778
5929
|
for node, (x, y) in pos.items():
|
@@ -5781,8 +5932,8 @@ def ppi(
|
|
5781
5932
|
|
5782
5933
|
# If ax is None, use plt.gca()
|
5783
5934
|
if ax is None:
|
5784
|
-
fig, ax = plt.subplots(1,1,figsize=figsize)
|
5785
|
-
|
5935
|
+
fig, ax = plt.subplots(1, 1, figsize=figsize)
|
5936
|
+
|
5786
5937
|
# Draw nodes, edges, and labels with customization options
|
5787
5938
|
nx.draw_networkx_nodes(
|
5788
5939
|
G,
|
@@ -5794,14 +5945,18 @@ def ppi(
|
|
5794
5945
|
edgecolors=edgecolor,
|
5795
5946
|
alpha=alpha,
|
5796
5947
|
hide_ticks=node_hideticks,
|
5797
|
-
node_shape=marker
|
5948
|
+
node_shape=marker,
|
5798
5949
|
)
|
5799
5950
|
|
5800
|
-
|
5951
|
+
# * linewidth
|
5801
5952
|
if not isinstance(linewidth, list):
|
5802
5953
|
linewidth = [linewidth] * G.number_of_edges()
|
5803
5954
|
else:
|
5804
|
-
linewidth = (
|
5955
|
+
linewidth = (
|
5956
|
+
linewidth[: G.number_of_edges()]
|
5957
|
+
if len(linewidth) > G.number_of_edges()
|
5958
|
+
else linewidth + [linewidth[-1]] * (G.number_of_edges() - len(linewidth))
|
5959
|
+
)
|
5805
5960
|
# Normalize linewidth if it is a list
|
5806
5961
|
if isinstance(linewidth, list):
|
5807
5962
|
min_linewidth, max_linewidth = min(linewidth), max(linewidth)
|
@@ -5809,7 +5964,10 @@ def ppi(
|
|
5809
5964
|
if max_linewidth > min_linewidth: # Avoid division by zero
|
5810
5965
|
# Scale between vmin and vmax
|
5811
5966
|
linewidth = [
|
5812
|
-
vmin
|
5967
|
+
vmin
|
5968
|
+
+ (vmax - vmin)
|
5969
|
+
* (lw - min_linewidth)
|
5970
|
+
/ (max_linewidth - min_linewidth)
|
5813
5971
|
for lw in linewidth
|
5814
5972
|
]
|
5815
5973
|
else:
|
@@ -5818,8 +5976,8 @@ def ppi(
|
|
5818
5976
|
else:
|
5819
5977
|
# If linewidth is a single value, convert it to a list of that value
|
5820
5978
|
linewidth = [linewidth] * G.number_of_edges()
|
5821
|
-
|
5822
|
-
if not isinstance(linecolor, str):
|
5979
|
+
# * linecolor
|
5980
|
+
if not isinstance(linecolor, str):
|
5823
5981
|
weights = [G[u][v]["weight"] for u, v in G.edges()]
|
5824
5982
|
norm = Normalize(vmin=min(weights), vmax=max(weights))
|
5825
5983
|
colormap = cm.get_cmap(line_cmap)
|
@@ -5829,45 +5987,58 @@ def ppi(
|
|
5829
5987
|
|
5830
5988
|
# * linealpha
|
5831
5989
|
if isinstance(linealpha, list):
|
5832
|
-
linealpha = (
|
5990
|
+
linealpha = (
|
5991
|
+
linealpha[: G.number_of_edges()]
|
5992
|
+
if len(linealpha) > G.number_of_edges()
|
5993
|
+
else linealpha + [linealpha[-1]] * (G.number_of_edges() - len(linealpha))
|
5994
|
+
)
|
5833
5995
|
min_alpha, max_alpha = linealphas # Use linealphas tuple for min and max values
|
5834
5996
|
if len(linealpha) > 0:
|
5835
5997
|
min_linealpha, max_linealpha = min(linealpha), max(linealpha)
|
5836
5998
|
if max_linealpha > min_linealpha: # Avoid division by zero
|
5837
5999
|
linealpha = [
|
5838
|
-
min_alpha
|
6000
|
+
min_alpha
|
6001
|
+
+ (max_alpha - min_alpha)
|
6002
|
+
* (ea - min_linealpha)
|
6003
|
+
/ (max_linealpha - min_linealpha)
|
5839
6004
|
for ea in linealpha
|
5840
6005
|
]
|
5841
6006
|
else:
|
5842
6007
|
linealpha = [(min_alpha + max_alpha) / 2] * len(linealpha)
|
5843
6008
|
else:
|
5844
|
-
linealpha = [1.0] * G.number_of_edges()
|
6009
|
+
linealpha = [1.0] * G.number_of_edges() # 如果设置有误,则将它设置成1.0
|
5845
6010
|
else:
|
5846
6011
|
linealpha = [linealpha] * G.number_of_edges() # Convert to list if single value
|
5847
6012
|
nx.draw_networkx_edges(
|
5848
|
-
G,
|
5849
|
-
pos,
|
5850
|
-
ax=ax,
|
5851
|
-
edge_color=linecolor,
|
6013
|
+
G,
|
6014
|
+
pos,
|
6015
|
+
ax=ax,
|
6016
|
+
edge_color=linecolor,
|
5852
6017
|
width=linewidth,
|
5853
6018
|
style=linestyle,
|
5854
|
-
arrowstyle=line_arrowstyle,
|
5855
|
-
alpha=linealpha
|
6019
|
+
arrowstyle=line_arrowstyle,
|
6020
|
+
alpha=linealpha,
|
5856
6021
|
)
|
5857
|
-
|
6022
|
+
|
5858
6023
|
nx.draw_networkx_labels(
|
5859
|
-
G,
|
6024
|
+
G,
|
6025
|
+
pos,
|
6026
|
+
ax=ax,
|
6027
|
+
font_size=fontsize,
|
6028
|
+
font_color=fontcolor,
|
6029
|
+
horizontalalignment=ha,
|
6030
|
+
verticalalignment=va,
|
5860
6031
|
)
|
5861
|
-
figsets(ax=ax
|
6032
|
+
figsets(ax=ax, **kws_figsets)
|
5862
6033
|
ax.axis("off")
|
5863
6034
|
if dir_save:
|
5864
6035
|
if not os.path.basename(dir_save):
|
5865
|
-
dir_save="_.html"
|
6036
|
+
dir_save = "_.html"
|
5866
6037
|
net.write_html(dir_save)
|
5867
|
-
nx.write_graphml(G, dir_save.replace(".html",".graphml")) # Export to GraphML
|
6038
|
+
nx.write_graphml(G, dir_save.replace(".html", ".graphml")) # Export to GraphML
|
5868
6039
|
print(f"could be edited in Cytoscape \n{dir_save.replace(".html",".graphml")}")
|
5869
|
-
ips.figsave(dir_save.replace(".html",".pdf"))
|
5870
|
-
return G,ax
|
6040
|
+
ips.figsave(dir_save.replace(".html", ".pdf"))
|
6041
|
+
return G, ax
|
5871
6042
|
|
5872
6043
|
|
5873
6044
|
def plot_map(
|
@@ -5886,6 +6057,7 @@ def plot_map(
|
|
5886
6057
|
save_path=None, # Path to save the map in offline mode
|
5887
6058
|
pydeck_map=False, # Whether to use pydeck for rendering (True for pydeck)
|
5888
6059
|
pydeck_style="mapbox://styles/mapbox/streets-v11", # Map style for pydeck
|
6060
|
+
verbose=True, # show usage
|
5889
6061
|
**kwargs, # Additional arguments for Folium Map
|
5890
6062
|
):
|
5891
6063
|
"""
|
@@ -5899,19 +6071,88 @@ def plot_map(
|
|
5899
6071
|
df_tiles = pd.DataFrame({"tiles": tiles_support})
|
5900
6072
|
fsave("....tiles.csv",df_tiles)
|
5901
6073
|
"""
|
6074
|
+
config_markers = """from folium import Icon
|
6075
|
+
# https://github.com/lennardv2/Leaflet.awesome-markers?tab=readme-ov-file
|
6076
|
+
markers = [
|
6077
|
+
{
|
6078
|
+
"location": [loc[0], loc[1]],
|
6079
|
+
"popup": "Center City",
|
6080
|
+
"tooltip": "Philadelphia",
|
6081
|
+
"icon": Icon(color="red", icon="flag"),
|
6082
|
+
},
|
6083
|
+
{
|
6084
|
+
"location": [loc[0], loc[1] + 0.05],
|
6085
|
+
"popup": "Rittenhouse Square",
|
6086
|
+
"tooltip": "A lovely park",
|
6087
|
+
"icon": Icon(
|
6088
|
+
color="purple", icon="flag", prefix="fa"
|
6089
|
+
), # Purple marker with "star" icon (Font Awesome)
|
6090
|
+
},
|
6091
|
+
]"""
|
6092
|
+
config_overlay = """
|
6093
|
+
from folium import Circle
|
6094
|
+
|
6095
|
+
circle = Circle(
|
6096
|
+
location=loc,
|
6097
|
+
radius=300, # In meters
|
6098
|
+
color="#EB686C",
|
6099
|
+
fill=True,
|
6100
|
+
fill_opacity=0.2,
|
6101
|
+
)
|
6102
|
+
markers = [
|
6103
|
+
{
|
6104
|
+
"location": [loc[0], loc[1]],
|
6105
|
+
"popup": "Center City",
|
6106
|
+
"tooltip": "Philadelphia",
|
6107
|
+
},
|
6108
|
+
{
|
6109
|
+
"location": [loc[0], loc[1] + 0.05],
|
6110
|
+
"popup": "Rittenhouse Square",
|
6111
|
+
"tooltip": "A lovely park",
|
6112
|
+
},
|
6113
|
+
]
|
6114
|
+
plot_map(loc, overlays=[circle], zoom_start=14)
|
6115
|
+
"""
|
6116
|
+
config_plugin = """
|
6117
|
+
from folium.plugins import HeatMap
|
6118
|
+
heat_data = [
|
6119
|
+
[48.54440975, 9.060237673391708, 1],
|
6120
|
+
[48.5421456, 9.057464182487431, 1],
|
6121
|
+
[48.54539175, 9.059915422200906, 1],
|
6122
|
+
]
|
6123
|
+
heatmap = HeatMap(
|
6124
|
+
heat_data,
|
6125
|
+
radius=5, # Increase the radius of each point
|
6126
|
+
blur=5, # Adjust the blurring effect
|
6127
|
+
min_opacity=0.4, # Make the heatmap semi-transparent
|
6128
|
+
max_zoom=16, # Zoom level at which points appear
|
6129
|
+
gradient={ # Define a custom gradient
|
6130
|
+
0.2: "blue",
|
6131
|
+
0.4: "lime",
|
6132
|
+
0.6: "yellow",
|
6133
|
+
1.0: "#A34B00",
|
6134
|
+
},
|
6135
|
+
)
|
6136
|
+
|
6137
|
+
plot_map(loc, plugins=[heatmap])
|
6138
|
+
"""
|
5902
6139
|
from pathlib import Path
|
5903
6140
|
|
5904
6141
|
# Get the current script's directory as a Path object
|
5905
6142
|
current_directory = Path(__file__).resolve().parent
|
5906
6143
|
if not "tiles_support" in locals():
|
5907
|
-
tiles_support =
|
5908
|
-
|
6144
|
+
tiles_support = (
|
6145
|
+
fload(current_directory / "data" / "tiles.csv", verbose=0)
|
6146
|
+
.iloc[:, 1]
|
6147
|
+
.tolist()
|
6148
|
+
)
|
6149
|
+
tiles = strcmp(tiles, tiles_support)[0]
|
5909
6150
|
import folium
|
5910
6151
|
import streamlit as st
|
5911
6152
|
import pydeck as pdk
|
5912
6153
|
from streamlit_folium import st_folium
|
5913
6154
|
from folium.plugins import HeatMap
|
5914
|
-
|
6155
|
+
|
5915
6156
|
if pydeck_map:
|
5916
6157
|
view = pdk.ViewState(
|
5917
6158
|
latitude=location[0],
|
@@ -5920,7 +6161,6 @@ def plot_map(
|
|
5920
6161
|
pitch=0,
|
5921
6162
|
)
|
5922
6163
|
|
5923
|
-
# Example Layer (can be replaced by your custom layers)
|
5924
6164
|
layer = pdk.Layer(
|
5925
6165
|
"ScatterplotLayer",
|
5926
6166
|
data=[{"lat": location[0], "lon": location[1]}],
|
@@ -5929,20 +6169,16 @@ def plot_map(
|
|
5929
6169
|
get_radius=1000,
|
5930
6170
|
)
|
5931
6171
|
|
5932
|
-
# Create the deck
|
5933
6172
|
deck = pdk.Deck(
|
5934
6173
|
layers=[layer],
|
5935
6174
|
initial_view_state=view,
|
5936
6175
|
map_style=pydeck_style,
|
5937
6176
|
)
|
5938
|
-
|
5939
|
-
# Render map in Streamlit
|
5940
6177
|
st.pydeck_chart(deck)
|
5941
6178
|
|
5942
6179
|
return deck # Return the pydeck map
|
5943
6180
|
|
5944
6181
|
else:
|
5945
|
-
# Initialize the base map (Folium)
|
5946
6182
|
m = folium.Map(
|
5947
6183
|
location=location,
|
5948
6184
|
zoom_start=zoom_start,
|
@@ -5950,39 +6186,39 @@ def plot_map(
|
|
5950
6186
|
scrollWheelZoom=scroll_wheel_zoom,
|
5951
6187
|
**kwargs,
|
5952
6188
|
)
|
5953
|
-
|
5954
|
-
# Add markers
|
5955
6189
|
if markers:
|
6190
|
+
if verbose:
|
6191
|
+
print(config_markers)
|
5956
6192
|
for marker in markers:
|
5957
6193
|
folium.Marker(
|
5958
6194
|
location=marker.get("location"),
|
5959
6195
|
popup=marker.get("popup"),
|
5960
6196
|
tooltip=marker.get("tooltip"),
|
5961
|
-
icon=marker.get(
|
6197
|
+
icon=marker.get(
|
6198
|
+
"icon", folium.Icon()
|
6199
|
+
), # Default icon if none specified
|
5962
6200
|
).add_to(m)
|
5963
6201
|
|
5964
|
-
# Add overlays
|
5965
6202
|
if overlays:
|
6203
|
+
if verbose:
|
6204
|
+
print(config_overlay)
|
5966
6205
|
for overlay in overlays:
|
5967
6206
|
overlay.add_to(m)
|
5968
6207
|
|
5969
|
-
# Add custom layers
|
5970
6208
|
if custom_layers:
|
5971
6209
|
for layer in custom_layers:
|
5972
6210
|
layer.add_to(m)
|
5973
6211
|
|
5974
|
-
# Add plugins
|
5975
6212
|
if plugins:
|
6213
|
+
if verbose:
|
6214
|
+
print(config_plugin)
|
5976
6215
|
for plugin in plugins:
|
5977
6216
|
plugin.add_to(m)
|
5978
6217
|
|
5979
|
-
# Fit map bounds
|
5980
6218
|
if fit_bounds:
|
5981
6219
|
m.fit_bounds(fit_bounds)
|
5982
6220
|
|
5983
|
-
# Handle rendering based on output
|
5984
6221
|
if output == "streamlit":
|
5985
|
-
# Render the map in Streamlit
|
5986
6222
|
st_data = st_folium(m, width=map_width, height=map_height)
|
5987
6223
|
return st_data
|
5988
6224
|
elif output == "offline":
|