py2ls 0.2.4.15__py3-none-any.whl → 0.2.4.16__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 +722 -12
- py2ls/ml2ls copy.py +2906 -0
- py2ls/ml2ls.py +345 -12
- py2ls/plot.py +409 -24
- {py2ls-0.2.4.15.dist-info → py2ls-0.2.4.16.dist-info}/METADATA +1 -1
- {py2ls-0.2.4.15.dist-info → py2ls-0.2.4.16.dist-info}/RECORD +8 -7
- {py2ls-0.2.4.15.dist-info → py2ls-0.2.4.16.dist-info}/WHEEL +0 -0
py2ls/plot.py
CHANGED
@@ -20,7 +20,9 @@ from .ips import (
|
|
20
20
|
flatten,
|
21
21
|
plt_font,
|
22
22
|
run_once_within,
|
23
|
+
df_format
|
23
24
|
)
|
25
|
+
import scipy.stats as scipy_stats
|
24
26
|
from .stats import *
|
25
27
|
import os
|
26
28
|
|
@@ -2255,7 +2257,10 @@ def figsets(*args, **kwargs):
|
|
2255
2257
|
colors = get_color(8)
|
2256
2258
|
matplotlib.rcParams["axes.prop_cycle"] = cycler(color=colors)
|
2257
2259
|
if len(fig.get_axes()) > 1:
|
2258
|
-
|
2260
|
+
try:
|
2261
|
+
plt.tight_layout()
|
2262
|
+
except Exception as e:
|
2263
|
+
print(e)
|
2259
2264
|
|
2260
2265
|
|
2261
2266
|
def split_legend(ax, n=2, loc=None, title=None, bbox=None, ncol=1, **kwargs):
|
@@ -3120,7 +3125,7 @@ def plotxy(
|
|
3120
3125
|
x=None,
|
3121
3126
|
y=None,
|
3122
3127
|
ax=None,
|
3123
|
-
|
3128
|
+
kind_: Union[str, list] = "scatter", # Specify the kind of plot
|
3124
3129
|
verbose=False,
|
3125
3130
|
**kwargs,
|
3126
3131
|
):
|
@@ -3155,23 +3160,23 @@ def plotxy(
|
|
3155
3160
|
|
3156
3161
|
valid_kinds = list(default_settings.keys())
|
3157
3162
|
# print(valid_kinds)
|
3158
|
-
if
|
3159
|
-
if isinstance(
|
3160
|
-
|
3161
|
-
|
3163
|
+
if kind_ is not None:
|
3164
|
+
if isinstance(kind_, str):
|
3165
|
+
kind_ = [kind_]
|
3166
|
+
kind_ = [strcmp(i, valid_kinds)[0] for i in kind_]
|
3162
3167
|
else:
|
3163
3168
|
verbose = True
|
3164
3169
|
|
3165
3170
|
if verbose:
|
3166
|
-
if
|
3167
|
-
for k in
|
3171
|
+
if kind_ is not None:
|
3172
|
+
for k in kind_:
|
3168
3173
|
if k in valid_kinds:
|
3169
3174
|
print(f"{k}:\n\t{default_settings[k]}")
|
3170
3175
|
usage_str = """plotxy(data=ranked_genes,
|
3171
3176
|
x="log2(fold_change)",
|
3172
3177
|
y="-log10(p-value)",
|
3173
3178
|
palette=get_color(3, cmap="coolwarm"),
|
3174
|
-
|
3179
|
+
kind_=["scatter","rug"],
|
3175
3180
|
kws_rug=dict(height=0.2),
|
3176
3181
|
kws_scatter=dict(s=20, color=get_color(3)[2]),
|
3177
3182
|
verbose=0)
|
@@ -3192,7 +3197,11 @@ def plotxy(
|
|
3192
3197
|
kwargs.pop(k_arg, None)
|
3193
3198
|
break
|
3194
3199
|
zorder = 0
|
3195
|
-
for k in
|
3200
|
+
for k in kind_:
|
3201
|
+
# preprocess data
|
3202
|
+
data=df_preprocessing_(data, kind=k)
|
3203
|
+
if 'variable' in data.columns and 'value' in data.columns:
|
3204
|
+
x,y='variable','value'
|
3196
3205
|
zorder += 1
|
3197
3206
|
# indicate 'col' features
|
3198
3207
|
col = kwargs.get("col", None)
|
@@ -3213,10 +3222,166 @@ def plotxy(
|
|
3213
3222
|
# (1) return FcetGrid
|
3214
3223
|
if k == "jointplot":
|
3215
3224
|
kws_joint = kwargs.pop("kws_joint", kwargs)
|
3225
|
+
stats=kwargs.pop("stats",True)
|
3226
|
+
if stats:
|
3227
|
+
r, p_value = scipy_stats.pearsonr(data[x], data[y])
|
3216
3228
|
g = sns.jointplot(data=data, x=x, y=y, **kws_joint)
|
3229
|
+
g.ax_joint.annotate(
|
3230
|
+
f"pearsonr = {r:.2f} p = {p_value:.3f}",
|
3231
|
+
xy=(0.6, 0.98),
|
3232
|
+
xycoords="axes fraction",
|
3233
|
+
fontsize=12,
|
3234
|
+
color="black",
|
3235
|
+
ha="center",
|
3236
|
+
)
|
3217
3237
|
elif k == "lmplot":
|
3218
3238
|
kws_lm = kwargs.pop("kws_lm", kwargs)
|
3219
|
-
|
3239
|
+
stats = kwargs.pop("stats", True) # Flag to calculate stats
|
3240
|
+
hue = kwargs.pop("hue", None) # Get the hue argument (if any)
|
3241
|
+
col = kwargs.pop("col", None) # Get the col argument (if any)
|
3242
|
+
row = kwargs.pop("row", None) # Get the row argument (if any)
|
3243
|
+
|
3244
|
+
# Create the linear model plot (lmplot)
|
3245
|
+
g = sns.lmplot(data=data, x=x, y=y, hue=hue, col=col, row=row, **kws_lm)
|
3246
|
+
|
3247
|
+
# Compute Pearson correlation and p-value statistics
|
3248
|
+
if stats:
|
3249
|
+
stats_per_facet = {}
|
3250
|
+
stats_per_hue = {}
|
3251
|
+
|
3252
|
+
# If no hue, col, or row, calculate stats for the entire dataset
|
3253
|
+
if all([hue is None, col is None, row is None]):
|
3254
|
+
r, p_value = scipy_stats.pearsonr(data[x], data[y])
|
3255
|
+
stats_per_facet[(None, None)] = (r, p_value) # Store stats for the entire dataset
|
3256
|
+
|
3257
|
+
else:
|
3258
|
+
if hue is None and (col is not None or row is not None):
|
3259
|
+
for ax in g.axes.flat:
|
3260
|
+
facet_name = ax.get_title()
|
3261
|
+
if '=' in facet_name:
|
3262
|
+
# Assume facet_name is like 'Column = Value'
|
3263
|
+
facet_column_name = facet_name.split('=')[0].strip() # Column name before '='
|
3264
|
+
facet_value_str = facet_name.split('=')[1].strip() # Facet value after '='
|
3265
|
+
|
3266
|
+
# Try converting facet_value to match the data type of the DataFrame column
|
3267
|
+
facet_column_dtype = data[facet_column_name].dtype
|
3268
|
+
if facet_column_dtype == 'int' or facet_column_dtype == 'float':
|
3269
|
+
facet_value = pd.to_numeric(facet_value_str, errors='coerce') # Convert to numeric
|
3270
|
+
else:
|
3271
|
+
facet_value = facet_value_str # Treat as a string if not numeric
|
3272
|
+
else:
|
3273
|
+
facet_column_name = facet_name.split('=')[0].strip() # Column name before '='
|
3274
|
+
facet_value=facet_name.split('=')[1].strip()
|
3275
|
+
facet_data = data[data[facet_column_name] == facet_value]
|
3276
|
+
if not facet_data.empty:
|
3277
|
+
r, p_value = scipy_stats.pearsonr(facet_data[x], facet_data[y])
|
3278
|
+
stats_per_facet[facet_name] = (r, p_value)
|
3279
|
+
else:
|
3280
|
+
stats_per_facet[facet_name] = (None, None) # Handle empty facets
|
3281
|
+
|
3282
|
+
# Annotate the stats on the plot
|
3283
|
+
for ax in g.axes.flat:
|
3284
|
+
if stats:
|
3285
|
+
# Adjust the position for each facet to avoid overlap
|
3286
|
+
idx=1
|
3287
|
+
shift_factor = 0.02 * idx # Adjust this factor as needed to prevent overlap
|
3288
|
+
y_position = 0.98 - shift_factor # Dynamic vertical shift for each facet
|
3289
|
+
|
3290
|
+
if all([hue is None, col is None, row is None]):
|
3291
|
+
# Use stats for the entire dataset if no hue, col, or row
|
3292
|
+
r, p_value = stats_per_facet.get((None, None), (None, None))
|
3293
|
+
if r is not None and p_value is not None:
|
3294
|
+
ax.annotate(
|
3295
|
+
f"pearsonr = {r:.2f} p = {p_value:.3f}",
|
3296
|
+
xy=(0.6, y_position),
|
3297
|
+
xycoords="axes fraction",
|
3298
|
+
fontsize=12,
|
3299
|
+
color="black",
|
3300
|
+
ha="center",
|
3301
|
+
)
|
3302
|
+
else:
|
3303
|
+
ax.annotate(
|
3304
|
+
"No stats available",
|
3305
|
+
xy=(0.6, y_position),
|
3306
|
+
xycoords="axes fraction",
|
3307
|
+
fontsize=12,
|
3308
|
+
color="black",
|
3309
|
+
ha="center",
|
3310
|
+
)
|
3311
|
+
elif hue is not None:
|
3312
|
+
if (col is None and row is None):
|
3313
|
+
hue_categories = sorted(flatten(data[hue],verbose=0))
|
3314
|
+
idx=1
|
3315
|
+
for category in hue_categories:
|
3316
|
+
subset_data = data[data[hue] == category]
|
3317
|
+
r, p_value = scipy_stats.pearsonr(subset_data[x], subset_data[y])
|
3318
|
+
stats_per_hue[category] = (r, p_value)
|
3319
|
+
shift_factor = 0.05 * idx # Adjust this factor as needed to prevent overlap
|
3320
|
+
y_position = 0.98 - shift_factor # Dynamic vertical shift for each facet
|
3321
|
+
ax.annotate(
|
3322
|
+
f"{category}: pearsonr = {r:.2f} p = {p_value:.3f}",
|
3323
|
+
xy=(0.6, y_position),
|
3324
|
+
xycoords="axes fraction",
|
3325
|
+
fontsize=12,
|
3326
|
+
color="black",
|
3327
|
+
ha="center",
|
3328
|
+
)
|
3329
|
+
idx+=1
|
3330
|
+
else:
|
3331
|
+
for ax in g.axes.flat:
|
3332
|
+
facet_name = ax.get_title()
|
3333
|
+
if '=' in facet_name:
|
3334
|
+
# Assume facet_name is like 'Column = Value'
|
3335
|
+
facet_column_name = facet_name.split('=')[0].strip() # Column name before '='
|
3336
|
+
facet_value_str = facet_name.split('=')[1].strip() # Facet value after '='
|
3337
|
+
|
3338
|
+
# Try converting facet_value to match the data type of the DataFrame column
|
3339
|
+
facet_column_dtype = data[facet_column_name].dtype
|
3340
|
+
if facet_column_dtype == 'int' or facet_column_dtype == 'float':
|
3341
|
+
facet_value = pd.to_numeric(facet_value_str, errors='coerce') # Convert to numeric
|
3342
|
+
else:
|
3343
|
+
facet_value = facet_value_str # Treat as a string if not numeric
|
3344
|
+
else:
|
3345
|
+
facet_column_name = facet_name.split('=')[0].strip() # Column name before '='
|
3346
|
+
facet_value=facet_name.split('=')[1].strip()
|
3347
|
+
facet_data = data[data[facet_column_name] == facet_value]
|
3348
|
+
if not facet_data.empty:
|
3349
|
+
r, p_value = scipy_stats.pearsonr(facet_data[x], facet_data[y])
|
3350
|
+
stats_per_facet[facet_name] = (r, p_value)
|
3351
|
+
else:
|
3352
|
+
stats_per_facet[facet_name] = (None, None) # Handle empty facets
|
3353
|
+
|
3354
|
+
ax.annotate(
|
3355
|
+
f"pearsonr = {r:.2f} p = {p_value:.3f}",
|
3356
|
+
xy=(0.6, y_position),
|
3357
|
+
xycoords="axes fraction",
|
3358
|
+
fontsize=12,
|
3359
|
+
color="black",
|
3360
|
+
ha="center",
|
3361
|
+
)
|
3362
|
+
elif hue is None and (col is not None or row is not None):
|
3363
|
+
# Annotate stats for each facet
|
3364
|
+
facet_name = ax.get_title()
|
3365
|
+
r, p_value = stats_per_facet.get(facet_name, (None, None))
|
3366
|
+
if r is not None and p_value is not None:
|
3367
|
+
ax.annotate(
|
3368
|
+
f"pearsonr = {r:.2f} p = {p_value:.3f}",
|
3369
|
+
xy=(0.6, y_position),
|
3370
|
+
xycoords="axes fraction",
|
3371
|
+
fontsize=12,
|
3372
|
+
color="black",
|
3373
|
+
ha="center",
|
3374
|
+
)
|
3375
|
+
else:
|
3376
|
+
ax.annotate(
|
3377
|
+
"No stats available",
|
3378
|
+
xy=(0.6, y_position),
|
3379
|
+
xycoords="axes fraction",
|
3380
|
+
fontsize=12,
|
3381
|
+
color="black",
|
3382
|
+
ha="center",
|
3383
|
+
)
|
3384
|
+
|
3220
3385
|
elif k == "catplot_sns":
|
3221
3386
|
kws_cat = kwargs.pop("kws_cat", kwargs)
|
3222
3387
|
g = sns.catplot(data=data, x=x, y=y, **kws_cat)
|
@@ -3317,7 +3482,22 @@ def plotxy(
|
|
3317
3482
|
elif k == "regplot":
|
3318
3483
|
kws_reg = kwargs.pop("kws_reg", kwargs)
|
3319
3484
|
kws_reg = {k: v for k, v in kws_reg.items() if not k.startswith("kws_")}
|
3320
|
-
|
3485
|
+
stats = kwargs.pop("stats", True) # Flag to calculate stats
|
3486
|
+
|
3487
|
+
# Compute Pearson correlation if stats is True
|
3488
|
+
if stats:
|
3489
|
+
r, p_value = scipy_stats.pearsonr(data[x], data[y])
|
3490
|
+
ax = sns.regplot(data=data, x=x, y=y, ax=ax, **kws_reg)
|
3491
|
+
|
3492
|
+
# Annotate the Pearson correlation and p-value
|
3493
|
+
ax.annotate(
|
3494
|
+
f"pearsonr = {r:.2f} p = {p_value:.3f}",
|
3495
|
+
xy=(0.6, 0.98),
|
3496
|
+
xycoords="axes fraction",
|
3497
|
+
fontsize=12,
|
3498
|
+
color="black",
|
3499
|
+
ha="center",
|
3500
|
+
)
|
3321
3501
|
elif k == "residplot":
|
3322
3502
|
kws_resid = kwargs.pop("kws_resid", kwargs)
|
3323
3503
|
kws_resid = {k: v for k, v in kws_resid.items() if not k.startswith("kws_")}
|
@@ -3332,7 +3512,7 @@ def plotxy(
|
|
3332
3512
|
figsets(ax=ax, **kws_figsets)
|
3333
3513
|
if kws_add_text:
|
3334
3514
|
add_text(ax=ax, **kws_add_text) if kws_add_text else None
|
3335
|
-
if run_once_within(
|
3515
|
+
if run_once_within(10):
|
3336
3516
|
print(f"\n{k}⤵ ")
|
3337
3517
|
print(default_settings[k])
|
3338
3518
|
# print("=>\t",sns_info[sns_info["Functions"].str.contains(k)].iloc[:, -1].tolist()[0],"\n")
|
@@ -3341,6 +3521,125 @@ def plotxy(
|
|
3341
3521
|
return g, ax
|
3342
3522
|
return ax
|
3343
3523
|
|
3524
|
+
import pandas as pd
|
3525
|
+
|
3526
|
+
|
3527
|
+
def df_preprocessing_(data, kind, verbose=False):
|
3528
|
+
"""
|
3529
|
+
Automatically formats data for various seaborn plot types.
|
3530
|
+
|
3531
|
+
Parameters:
|
3532
|
+
- data (pd.DataFrame): Original DataFrame.
|
3533
|
+
- kind (str): Type of seaborn plot, e.g., "heatmap", "boxplot", "violinplot", "lineplot", "scatterplot", "histplot", "kdeplot", "catplot", "barplot".
|
3534
|
+
- verbose (bool): If True, print detailed information about the data format conversion.
|
3535
|
+
|
3536
|
+
Returns:
|
3537
|
+
- pd.DataFrame: Formatted DataFrame ready for the specified seaborn plot type.
|
3538
|
+
"""
|
3539
|
+
# Determine data format: 'long', 'wide', or 'uncertain'
|
3540
|
+
df_format_ = df_format(data)
|
3541
|
+
|
3542
|
+
# Correct plot type name
|
3543
|
+
kind = strcmp(
|
3544
|
+
kind,
|
3545
|
+
[
|
3546
|
+
"heatmap",
|
3547
|
+
"pairplot",
|
3548
|
+
"jointplot", # Typically requires wide format for axis variables
|
3549
|
+
"facetgrid", # Used for creating small multiples (can work with wide format)
|
3550
|
+
"barplot", # Can be used with wide format
|
3551
|
+
"pointplot", # Works well with wide format
|
3552
|
+
"pivot_table", # Works with wide format (aggregated data)
|
3553
|
+
"boxplot",
|
3554
|
+
"violinplot",
|
3555
|
+
"stripplot",
|
3556
|
+
"swarmplot",
|
3557
|
+
"catplot",
|
3558
|
+
"lineplot",
|
3559
|
+
"scatterplot",
|
3560
|
+
"relplot",
|
3561
|
+
"barplot", # Can also work with long format (aggregated data in long form)
|
3562
|
+
"boxenplot", # Similar to boxplot, works with long format
|
3563
|
+
"countplot", # Works best with long format (categorical data)
|
3564
|
+
"heatmap", # Can work with long format after reshaping
|
3565
|
+
"lineplot", # Can work with long format (time series, continuous)
|
3566
|
+
"histplot", # Can be used with both wide and long formats
|
3567
|
+
"kdeplot", # Works with both wide and long formats
|
3568
|
+
"ecdfplot", # Works with both formats
|
3569
|
+
"scatterplot", # Can work with both formats depending on data structure
|
3570
|
+
"lineplot", # Can work with both wide and long formats
|
3571
|
+
"area plot", # Can work with both formats, useful for stacked areas
|
3572
|
+
"violinplot", # Can work with both formats depending on categorical vs continuous data
|
3573
|
+
],
|
3574
|
+
)[0]
|
3575
|
+
|
3576
|
+
wide_kinds = [
|
3577
|
+
"pairplot",
|
3578
|
+
]
|
3579
|
+
|
3580
|
+
# Define plot types that require 'long' format
|
3581
|
+
long_kinds = [
|
3582
|
+
"catplot",
|
3583
|
+
]
|
3584
|
+
|
3585
|
+
# Flexible kinds: distribution plots can use either format
|
3586
|
+
flexible_kinds = [
|
3587
|
+
"jointplot", # Typically requires wide format for axis variables
|
3588
|
+
"lineplot", # Can work with long format (time series, continuous)
|
3589
|
+
"lineplot",
|
3590
|
+
"scatterplot",
|
3591
|
+
"barplot", # Can also work with long format (aggregated data in long form)
|
3592
|
+
"boxenplot", # Similar to boxplot, works with long format
|
3593
|
+
"countplot", # Works best with long format (categorical data)
|
3594
|
+
"regplot",
|
3595
|
+
"violinplot",
|
3596
|
+
"stripplot",
|
3597
|
+
"swarmplot",
|
3598
|
+
"boxplot",
|
3599
|
+
"histplot", # Can be used with both wide and long formats
|
3600
|
+
"kdeplot", # Works with both wide and long formats
|
3601
|
+
"ecdfplot", # Works with both formats
|
3602
|
+
"scatterplot", # Can work with both formats depending on data structure
|
3603
|
+
"lineplot", # Can work with both wide and long formats
|
3604
|
+
"area plot", # Can work with both formats, useful for stacked areas
|
3605
|
+
"violinplot", # Can work with both formats depending on categorical vs continuous data
|
3606
|
+
"relplot",
|
3607
|
+
"pointplot", # Works well with wide format
|
3608
|
+
]
|
3609
|
+
|
3610
|
+
# Wide format (e.g., for heatmap and pairplot)
|
3611
|
+
if kind in wide_kinds:
|
3612
|
+
if df_format_ != "wide":
|
3613
|
+
if verbose:
|
3614
|
+
print("Converting to wide format for", kind)
|
3615
|
+
return data.corr() if kind == "heatmap" else data
|
3616
|
+
return data
|
3617
|
+
|
3618
|
+
# Long format for categorical plots or time series
|
3619
|
+
elif kind in long_kinds:
|
3620
|
+
if df_format_ == "wide":
|
3621
|
+
if verbose:
|
3622
|
+
print("Converting wide data to long format for", kind)
|
3623
|
+
return pd.melt(data, var_name="variable", value_name="value")
|
3624
|
+
elif df_format_ == "uncertain":
|
3625
|
+
if verbose:
|
3626
|
+
print("Data format is uncertain, attempting to melt for", kind)
|
3627
|
+
return pd.melt(data, var_name="variable", value_name="value")
|
3628
|
+
return data
|
3629
|
+
|
3630
|
+
# Flexible format: distribution plots can use either long or wide
|
3631
|
+
elif kind in flexible_kinds:
|
3632
|
+
if df_format_ == "wide" or df_format_ == "long":
|
3633
|
+
return data
|
3634
|
+
if verbose:
|
3635
|
+
print("Converting uncertain format to long format for distribution plots")
|
3636
|
+
return pd.melt(data, var_name="variable", value_name="value")
|
3637
|
+
|
3638
|
+
else:
|
3639
|
+
if verbose:
|
3640
|
+
print("Unrecognized plot type; returning original data without conversion.")
|
3641
|
+
return data
|
3642
|
+
|
3344
3643
|
|
3345
3644
|
def norm_cmap(data, cmap="coolwarm", min_max=[0, 1]):
|
3346
3645
|
norm_ = plt.Normalize(min_max[0], min_max[1])
|
@@ -4103,6 +4402,7 @@ def subplot(
|
|
4103
4402
|
figsize: Union[tuple, list] = [8, 8],
|
4104
4403
|
sharex=False,
|
4105
4404
|
sharey=False,
|
4405
|
+
verbose=False,
|
4106
4406
|
**kwargs,
|
4107
4407
|
):
|
4108
4408
|
"""
|
@@ -4125,23 +4425,32 @@ def subplot(
|
|
4125
4425
|
"""
|
4126
4426
|
from matplotlib.gridspec import GridSpec
|
4127
4427
|
|
4128
|
-
if
|
4428
|
+
if verbose:
|
4129
4429
|
print(
|
4130
|
-
f"usage:\n\tnexttile = subplot(2, 2, figsize=(5, 5), sharex=
|
4430
|
+
f"usage:\n\tnexttile = subplot(2, 2, figsize=(5, 5), sharex=False, sharey=False)\n\tax = nexttile()"
|
4131
4431
|
)
|
4132
|
-
|
4432
|
+
|
4433
|
+
figsize_recommend = f"subplot({rows}, {cols}, figsize={figsize})"
|
4434
|
+
|
4435
|
+
fig = plt.figure(figsize=figsize, constrained_layout=True)
|
4133
4436
|
grid_spec = GridSpec(rows, cols, figure=fig)
|
4134
4437
|
occupied = set()
|
4135
4438
|
row_first_axes = [None] * rows # Track the first axis in each row (for sharey)
|
4136
4439
|
col_first_axes = [None] * cols # Track the first axis in each column (for sharex)
|
4137
4440
|
|
4138
4441
|
def expand_ax():
|
4139
|
-
nonlocal rows, grid_spec
|
4442
|
+
nonlocal rows, grid_spec,cols,row_first_axes,fig,figsize,figsize_recommend
|
4443
|
+
# fig_height = fig.get_figheight()
|
4444
|
+
# subplot_height = fig_height / rows
|
4140
4445
|
rows += 1 # Expands by adding a row
|
4446
|
+
# figsize = (figsize[0], fig_height+subplot_height)
|
4447
|
+
fig.set_size_inches(figsize)
|
4141
4448
|
grid_spec = GridSpec(rows, cols, figure=fig)
|
4142
|
-
|
4449
|
+
row_first_axes.append(None)
|
4450
|
+
figsize_recommend=f"Warning: 建议设置 subplot({rows}, {cols})"
|
4451
|
+
print(figsize_recommend)
|
4143
4452
|
def nexttile(rowspan=1, colspan=1, **kwargs):
|
4144
|
-
nonlocal rows, cols, occupied, grid_spec
|
4453
|
+
nonlocal rows, cols, occupied, grid_spec,fig,figsize_recommend
|
4145
4454
|
for row in range(rows):
|
4146
4455
|
for col in range(cols):
|
4147
4456
|
if all(
|
@@ -4153,6 +4462,7 @@ def subplot(
|
|
4153
4462
|
else:
|
4154
4463
|
continue
|
4155
4464
|
break
|
4465
|
+
|
4156
4466
|
else:
|
4157
4467
|
expand_ax()
|
4158
4468
|
return nexttile(rowspan=rowspan, colspan=colspan, **kwargs)
|
@@ -4161,7 +4471,6 @@ def subplot(
|
|
4161
4471
|
|
4162
4472
|
if sharex:
|
4163
4473
|
sharex_ax = col_first_axes[col]
|
4164
|
-
|
4165
4474
|
if sharey:
|
4166
4475
|
sharey_ax = row_first_axes[row]
|
4167
4476
|
ax = fig.add_subplot(
|
@@ -4170,22 +4479,24 @@ def subplot(
|
|
4170
4479
|
sharey=sharey_ax,
|
4171
4480
|
**kwargs,
|
4172
4481
|
)
|
4482
|
+
|
4173
4483
|
if row_first_axes[row] is None:
|
4174
4484
|
row_first_axes[row] = ax
|
4175
4485
|
if col_first_axes[col] is None:
|
4176
4486
|
col_first_axes[col] = ax
|
4487
|
+
|
4177
4488
|
for r in range(row, row + rowspan):
|
4178
4489
|
for c in range(col, col + colspan):
|
4179
4490
|
occupied.add((r, c))
|
4180
|
-
|
4491
|
+
|
4181
4492
|
return ax
|
4182
|
-
|
4183
4493
|
return nexttile
|
4184
4494
|
|
4185
4495
|
|
4186
4496
|
#! radar chart
|
4187
4497
|
def radar(
|
4188
4498
|
data: pd.DataFrame,
|
4499
|
+
title="Radar Chart",
|
4189
4500
|
ylim=(0, 100),
|
4190
4501
|
color=get_color(5),
|
4191
4502
|
fontsize=10,
|
@@ -4196,11 +4507,11 @@ def radar(
|
|
4196
4507
|
alpha=0.5,
|
4197
4508
|
marker="o",
|
4198
4509
|
edgecolor="none",
|
4199
|
-
edge_linewidth=0,
|
4510
|
+
edge_linewidth=0.5,
|
4200
4511
|
bg_color="0.8",
|
4201
4512
|
bg_alpha=None,
|
4202
4513
|
grid_interval_ratio=0.2,
|
4203
|
-
|
4514
|
+
show_value=False,# show text for each value
|
4204
4515
|
cmap=None,
|
4205
4516
|
legend_loc="upper right",
|
4206
4517
|
legend_fontsize=10,
|
@@ -4215,6 +4526,7 @@ def radar(
|
|
4215
4526
|
turning=None,
|
4216
4527
|
ax=None,
|
4217
4528
|
sp=2,
|
4529
|
+
verbose=True,
|
4218
4530
|
**kwargs,
|
4219
4531
|
):
|
4220
4532
|
"""
|
@@ -4239,6 +4551,7 @@ def radar(
|
|
4239
4551
|
- linestyle (str): Line style for the plot lines.
|
4240
4552
|
- alpha (float): The transparency level for the filled area.
|
4241
4553
|
- marker (str): The marker style for the data points.
|
4554
|
+
- value_offset=0.93,# offset of the text of each value
|
4242
4555
|
- edgecolor (str): The color for the marker edges.
|
4243
4556
|
- edge_linewidth (int): Line width for the marker edges.
|
4244
4557
|
- bg_color (str): Background color for the radar chart.
|
@@ -4260,6 +4573,43 @@ def radar(
|
|
4260
4573
|
- sp (int): Padding for the ticks from the plot area.
|
4261
4574
|
- **kwargs: Additional arguments for customization.
|
4262
4575
|
"""
|
4576
|
+
if run_once_within() and verbose:
|
4577
|
+
usage_="""usage:
|
4578
|
+
radar(
|
4579
|
+
data: pd.DataFrame, #The data to plot. Each column corresponds to a variable, and each row represents a data point.
|
4580
|
+
title="Radar Chart",
|
4581
|
+
ylim=(0, 100),# ylim (tuple): The limits of the radial axis (y-axis). Default is (0, 100).
|
4582
|
+
color=get_color(5),#The color(s) for the plot. Can be a single color or a list of colors.
|
4583
|
+
fontsize=10,# Font size for the angular labels (x-axis).
|
4584
|
+
fontcolor="k",# Color for the angular labels.
|
4585
|
+
size=6,#The size of the markers for each data point.
|
4586
|
+
linewidth=1,
|
4587
|
+
linestyle="-",
|
4588
|
+
alpha=0.5,#for the filled area.
|
4589
|
+
marker="o",# for the data points.
|
4590
|
+
edgecolor="none",#for the marker edges.
|
4591
|
+
edge_linewidth=0.5,#for the marker edges.
|
4592
|
+
bg_color="0.8",
|
4593
|
+
bg_alpha=None,
|
4594
|
+
grid_interval_ratio=0.2,#Determines the intervals for the grid lines as a fraction of the y-limit.
|
4595
|
+
show_value=False,# show text for each value
|
4596
|
+
cmap=None,
|
4597
|
+
legend_loc="upper right",
|
4598
|
+
legend_fontsize=10,
|
4599
|
+
grid_color="gray",
|
4600
|
+
grid_alpha=0.5,
|
4601
|
+
grid_linestyle="--",
|
4602
|
+
grid_linewidth=0.5,
|
4603
|
+
circular: bool = False,#If True, use circular grid lines. If False, use spider-style grid lines (straight lines)
|
4604
|
+
tick_fontsize=None,#for the radial (y-axis) labels.
|
4605
|
+
tick_fontcolor="0.65",#for the radial (y-axis) labels.
|
4606
|
+
tick_loc=None, # label position
|
4607
|
+
turning=None,#Rotation of the radar chart
|
4608
|
+
ax=None,
|
4609
|
+
sp=2,#Padding for the ticks from the plot area.
|
4610
|
+
**kwargs,
|
4611
|
+
)"""
|
4612
|
+
print(usage_)
|
4263
4613
|
if circular:
|
4264
4614
|
from matplotlib.colors import to_rgba
|
4265
4615
|
kws_figsets = {}
|
@@ -4371,6 +4721,41 @@ def radar(
|
|
4371
4721
|
clip_on=False,
|
4372
4722
|
)
|
4373
4723
|
ax.fill(angles, values, color=colors[i], alpha=alpha)
|
4724
|
+
# Add text labels for each value at each angle
|
4725
|
+
labeled_points = set() #这样同一个点就不会标多次了
|
4726
|
+
if show_value:
|
4727
|
+
for angle, value in zip(angles, values):
|
4728
|
+
if (angle, value) not in labeled_points:
|
4729
|
+
# offset_radius = value * value_offset
|
4730
|
+
lim_ = np.max(values)
|
4731
|
+
sep_in = lim_/5
|
4732
|
+
sep_low=sep_in*2
|
4733
|
+
sep_med=sep_in*3
|
4734
|
+
sep_hig=sep_in*4
|
4735
|
+
sep_out=lim_*5
|
4736
|
+
if value<sep_in:
|
4737
|
+
offset_radius = value * 0.7
|
4738
|
+
elif value<sep_low:
|
4739
|
+
offset_radius = value * 0.8
|
4740
|
+
elif sep_low<=value<sep_med:
|
4741
|
+
offset_radius = value * 0.85
|
4742
|
+
elif sep_med<=value<sep_hig:
|
4743
|
+
offset_radius = value * 0.9
|
4744
|
+
elif sep_hig<=value<sep_out:
|
4745
|
+
offset_radius = value * 0.93
|
4746
|
+
else:
|
4747
|
+
offset_radius = value * 0.98
|
4748
|
+
ax.text(
|
4749
|
+
angle,
|
4750
|
+
offset_radius,
|
4751
|
+
str(value),
|
4752
|
+
ha="center",
|
4753
|
+
va="center",
|
4754
|
+
fontsize=fontsize,
|
4755
|
+
color=fontcolor,
|
4756
|
+
zorder=11
|
4757
|
+
)
|
4758
|
+
labeled_points.add((angle, value))
|
4374
4759
|
|
4375
4760
|
ax.set_ylim(ylim)
|
4376
4761
|
# Add markers for each data point
|
@@ -17,7 +17,7 @@ py2ls/.git/hooks/pre-receive.sample,sha256=pMPSuce7P9jRRBwxvU7nGlldZrRPz0ndsxAlI
|
|
17
17
|
py2ls/.git/hooks/prepare-commit-msg.sample,sha256=6d3KpBif3dJe2X_Ix4nsp7bKFjkLI5KuMnbwyOGqRhk,1492
|
18
18
|
py2ls/.git/hooks/push-to-checkout.sample,sha256=pT0HQXmLKHxt16-mSu5HPzBeZdP0lGO7nXQI7DsSv18,2783
|
19
19
|
py2ls/.git/hooks/update.sample,sha256=jV8vqD4QPPCLV-qmdSHfkZT0XL28s32lKtWGCXoU0QY,3650
|
20
|
-
py2ls/.git/index,sha256=
|
20
|
+
py2ls/.git/index,sha256=2psUA1HSf13h_hMIjiDXo3a-eKs7JT7vYt6myqyT568,4232
|
21
21
|
py2ls/.git/info/exclude,sha256=ZnH-g7egfIky7okWTR8nk7IxgFjri5jcXAbuClo7DsE,240
|
22
22
|
py2ls/.git/logs/HEAD,sha256=8ID7WuAe_TlO9g-ARxhIJYdgdL3u3m7-1qrOanaIUlA,3535
|
23
23
|
py2ls/.git/logs/refs/heads/main,sha256=8ID7WuAe_TlO9g-ARxhIJYdgdL3u3m7-1qrOanaIUlA,3535
|
@@ -234,17 +234,18 @@ py2ls/export_requirements.py,sha256=x2WgUF0jYKz9GfA1MVKN-MdsM-oQ8yUeC6Ua8oCymio,
|
|
234
234
|
py2ls/fetch_update.py,sha256=9LXj661GpCEFII2wx_99aINYctDiHni6DOruDs_fdt8,4752
|
235
235
|
py2ls/freqanalysis.py,sha256=F4218VSPbgL5tnngh6xNCYuNnfR-F_QjECUUxrPYZss,32594
|
236
236
|
py2ls/ich2ls.py,sha256=3E9R8oVpyYZXH5PiIQgT3CN5NxLe4Dwtm2LwaeacE6I,21381
|
237
|
-
py2ls/ips.py,sha256=
|
238
|
-
py2ls/ml2ls.py,sha256=
|
237
|
+
py2ls/ips.py,sha256=YlBLv69l2ILYO9jGqHZss7AydNHCoq51qqu3b443cv0,297616
|
238
|
+
py2ls/ml2ls copy.py,sha256=iZJrFLIrdfTieAY2BDsxQFTm29smwnJh0aC4hRB9VGM,113314
|
239
|
+
py2ls/ml2ls.py,sha256=ldNxpo7JKekDai5Izn0pk1wQ1fcNFHZx0huoK_ypfvw,142109
|
239
240
|
py2ls/mol.py,sha256=AZnHzarIk_MjueKdChqn1V6e4tUle3X1NnHSFA6n3Nw,10645
|
240
241
|
py2ls/netfinder.py,sha256=R70NkrnO8LlXjT1y7bf2TN-yE4yOeAYhb0jDBiNp8XA,57536
|
241
242
|
py2ls/ocr.py,sha256=5lhUbJufIKRSOL6wAWVLEo8TqMYSjoI_Q-IO-_4u3DE,31419
|
242
|
-
py2ls/plot.py,sha256=
|
243
|
+
py2ls/plot.py,sha256=jFBglmV-czTxGlmhZ4VhGzN5shnYw3hFV2JoosoSW9U,190457
|
243
244
|
py2ls/setuptools-70.1.0-py3-none-any.whl,sha256=2bi3cUVal8ip86s0SOvgspteEF8SKLukECi-EWmFomc,882588
|
244
245
|
py2ls/sleep_events_detectors.py,sha256=bQA3HJqv5qnYKJJEIhCyhlDtkXQfIzqksnD0YRXso68,52145
|
245
246
|
py2ls/stats.py,sha256=qBn2rJmNa_QLLUqjwYqXUlGzqmW94sgA1bxJU2FC3r0,39175
|
246
247
|
py2ls/translator.py,sha256=77Tp_GjmiiwFbEIJD_q3VYpQ43XL9ZeJo6Mhl44mvh8,34284
|
247
248
|
py2ls/wb_detector.py,sha256=7y6TmBUj9exCZeIgBAJ_9hwuhkDh1x_-yg4dvNY1_GQ,6284
|
248
|
-
py2ls-0.2.4.
|
249
|
-
py2ls-0.2.4.
|
250
|
-
py2ls-0.2.4.
|
249
|
+
py2ls-0.2.4.16.dist-info/METADATA,sha256=z431Uha36h4d6syqBxzeNEsOwrXAp2yCya_q19-hoYo,20046
|
250
|
+
py2ls-0.2.4.16.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
251
|
+
py2ls-0.2.4.16.dist-info/RECORD,,
|
File without changes
|