Skip to content

Add string option for metrics - #504

Merged
ecomodeller merged 18 commits into
mainfrom
skill_table_expanded
Mar 11, 2025
Merged

Add string option for metrics#504
ecomodeller merged 18 commits into
mainfrom
skill_table_expanded

Conversation

@stkistner

@stkistnerstkistner commented Feb 14, 2025

Copy link
Copy Markdown
Collaborator

An idea for 'special metrics':

The concept is that metrics can also produce string outputs. The main purpose for this is to add auxiliary info to the metrics, e.g. for Peak Ratios we often would like to know how many peaks there were:

image

While not currently used in modelskill itself, but applications using modelskill.

The downside is once the value is set, rounding of numbers would be tricky... But I don't know of any alternative (quick) solution to provide auxiliary metrics without breaking everything.

@ecomodeller

Copy link
Copy Markdown
Member

Do you have other examples than the peak ratio, where it would be relevant with additional output?

@stkistner

Copy link
Copy Markdown
CollaboratorAuthor

Do you have other examples than the peak ratio, where it would be relevant with additional output?

Our "old" matlab repo included percentages relative to the observations mean, and a statement that SI is unbiased, e.g. here is a full example, taken from the Matlab equivalent:
image

@daniel-caichac-DHI

daniel-caichac-DHI commented Feb 14, 2025

Copy link
Copy Markdown
Collaborator

I agree that the (unbiased) str is another good example.
The %'s are kind of random if you ask me, because it is a % of what? 4.7% bias is defined how exactly...
or the one that puzzles me the most is the % next to the mean
mean = 104.7% .... ??

but yeah not trying to butcher that plot, I think that the idea behind it is still worthy, and there could be more applications that we do not know yet

@jsmariegaard

Copy link
Copy Markdown
Member

But maybe it belongs more generally to the SkillTable than just the skill table next to the scatter plot... ?

@stkistner

Copy link
Copy Markdown
CollaboratorAuthor

I agree that the (unbiased) str is another good example. The %'s are kind of random if you ask me, because it is a % of what? 4.7% bias is defined how exactly... or the one that puzzles me the most is the % next to the meanmean = 104.7% .... ??

The percentages are relative to the observation mean. I do not care that much for them, but can be useful still.

But maybe it belongs more generally to the SkillTable than just the skill table next to the scatter plot... ?

That is the longer (and better) option, but it will likely require some like an auxiliary metrics class / attribute. I'm not 100% what the solution would look like. If you think this is work pursuing we can look into it.

fmt = f".{precision}f"
fvalue = f"{rounded_value:{fmt}}"
else:
fvalue = str(value)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would this work then, if I have a skill called for instance PR and the value is 1.17, how would you add the text on the right as you did in your example picture ?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as in this

image

Copy link
Copy Markdown
CollaboratorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The metric output is

str=f"{pr:.2f} (N={n_joint}"

@daniel-caichac-DHIdaniel-caichac-DHIFeb 17, 2025

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean... it works, but I guess it means that when creating a metric (eg BIAS) if I wanted something special (say BIAS_str)
instead of

def bias(obs: ArrayLike, model: ArrayLike) -> Any:
r"""Bias (mean error)
$$
bias=\frac{1}{n}\sum_{i=1}^n (model_i - obs_i)
$$
Range: $(-\infty, \infty)$; Best: 0
"""
assert obs.size == model.size
return np.mean(model - obs)

the user would need to do

def bias_str(obs: ArrayLike, model: ArrayLike) -> Any:
r"""Bias (mean error)
$$
bias=\frac{1}{n}\sum_{i=1}^n (model_i - obs_i)
$$
Range: $(-\infty, \infty)$; Best: 0
"""
assert obs.size == model.size
bias = np.mean(model - obs)
return f'bias {bias:.2f} this is a bias string'

?
I see nothing wrong with the current code addition, so I am pro-approving it, if @ecomodeller agrees

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure I get this, let's book a meeting to come up with a pragmatic solution.

@stkistner

Copy link
Copy Markdown
CollaboratorAuthor

The string option is added (bnothing new, compared to before) and confirmed working with plotly. Some basic tests added to confirm it is working. It doesn't always work well with units (as that will always follow the metric output, but the end user should take care of that.
image

Also added now dict mapping for skill_table to rename the display names:
image

@stkistner

Copy link
Copy Markdown
CollaboratorAuthor

@daniel-caichac-DHI / @ecomodeller , any comments?

@daniel-caichac-DHI

Copy link
Copy Markdown
Collaborator

This is cool
image
Since I have struggled to add the skill Mean_model and Mean_obs as it was too long, but now it should fit well :)

@daniel-caichac-DHIdaniel-caichac-DHI left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it looks great so I will approve,
but I guess @ecomodeller should press merge, unless he has any comments

Comment threadmodelskill/plotting/_scatter.py Outdated
Comment threadtests/test_multimodelcompare.py Outdated
t = child
break

assert t._cells[1, 0]._text._text == custom_name1

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The skill table next to the scatter plot is starting to get complex enough that it deserves to be able to be tested independent from the scatter method.

@stkistner

Copy link
Copy Markdown
CollaboratorAuthor

@ecomodeller I've,

  • removed the argument from scatter plot
  • updated metric decorator to accept display_name - effectively replaces this dictionary argument added to scatter table.
  • Updated examples in notebook
  • scatter table now has its own dedicated tests

@daniel-caichac-DHI

Copy link
Copy Markdown
Collaborator

@ecomodeller could we merge this now? or u still have comments?

@ecomodeller
ecomodeller self-requested a review March 11, 2025 09:50
@ecomodeller
ecomodeller merged commit 91a927c into mainMar 11, 2025
@ecomodeller
ecomodeller deleted the skill_table_expanded branch March 11, 2025 09:51
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@stkistner@ecomodeller@daniel-caichac-DHI@jsmariegaard