Skip to content

Commit de09428

Browse files
authored
Merge pull request #298 from openscm/future-warning-pd
Fix deprecation warnings
2 parents 7813392 + ea5bcb5 commit de09428

10 files changed

Lines changed: 39 additions & 45 deletions

File tree

changelog/298.improvement.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Update to avoid hitting DeprecationWarning in pandas and seaborn
2+
3+
This should help reduce so many warnings appearing when doing common operations.

changelog/298.trivial.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lazy load pyam

docs/source/notebooks/plotting-with-seaborn.py

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# extension: .py
77
# format_name: percent
88
# format_version: '1.3'
9-
# jupytext_version: 1.14.5
9+
# jupytext_version: 1.15.2
1010
# kernelspec:
1111
# display_name: Python 3 (ipykernel)
1212
# language: python
@@ -23,7 +23,6 @@
2323
# more than the most basic plots.
2424

2525
# %%
26-
2726
import matplotlib.pyplot as plt
2827
import seaborn as sns
2928

@@ -36,7 +35,6 @@
3635
# For this notebook we use the RCMIP radiative forcings, available at rcmip.org.
3736

3837
# %%
39-
4038
rcmip_db = ScmRun("rcmip-radiative-forcing-annual-means-v4-0-0.csv")
4139
rcmip_db.head()
4240

@@ -46,7 +44,6 @@
4644
# For the most common plotting patterns, we provide a very simple `lineplot` method in `ScmRun`.
4745

4846
# %%
49-
5047
out = rcmip_db.filter(variable="Effective Radiative Forcing").lineplot()
5148
out
5249

@@ -60,7 +57,6 @@
6057
# specify the order to display the scenarios in.
6158

6259
# %%
63-
6460
ax = plt.figure(figsize=(16, 9)).add_subplot(111)
6561
rcmip_db.filter(variable="Effective Radiative Forcing").lineplot(
6662
ax=ax,
@@ -82,7 +78,6 @@
8278
print(rcmip_db.lineplot.__doc__)
8379

8480
# %%
85-
8681
fig, axes = plt.subplots(figsize=(16, 9), nrows=2, ncols=2)
8782

8883
pdb = rcmip_db.filter(variable="Effective Radiative Forcing")
@@ -113,11 +108,9 @@
113108
# These same options can also be passed to the `timeseries` and `long_data` methods.
114109

115110
# %%
116-
117111
rcmip_db.timeseries(time_axis="year-month")
118112

119113
# %%
120-
121114
rcmip_db.long_data(time_axis="days since 1970-01-01")
122115

123116
# %% [markdown]
@@ -146,7 +139,6 @@
146139
vars_to_plot
147140

148141
# %%
149-
150142
seaborn_df = rcmip_db.filter(variable=vars_to_plot).long_data()
151143
seaborn_df.head()
152144

@@ -155,7 +147,6 @@
155147
# [seaborn.relplot](https://seaborn.pydata.org/generated/seaborn.relplot.html).
156148

157149
# %%
158-
159150
sns.relplot(
160151
data=seaborn_df,
161152
x="time",
@@ -178,17 +169,14 @@
178169
# different scenarios. In such a case we can reshape the data using pandas before using seaborn.
179170

180171
# %%
181-
182172
ts = rcmip_db.filter(variable=vars_to_plot[:4]).timeseries()
183173
ts.head()
184174

185175
# %%
186-
187176
ts_reshaped = ts.unstack("variable").stack("time").reset_index()
188177
ts_reshaped.head()
189178

190179
# %%
191-
192180
sns.pairplot(
193181
ts_reshaped,
194182
hue="scenario",

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ xarray = "*"
4242
nc-time-axis = { version = ">=1.2.0", optional = true }
4343
typing-extensions = "*"
4444
matplotlib = { version = "^3.7.1", optional = true }
45-
seaborn = { version = "*", optional = true }
45+
seaborn = { version = ">=0.12.0", optional = true }
4646
netCDF4 = { version = "*", optional = true }
4747
openpyxl = { version = "*", optional = true }
4848
xlrd = { version = "*", optional = true }

src/scmdata/plotting.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ def lineplot(self, time_axis=None, **kwargs): # pragma: no cover
7575
if "scenario" in self.meta_attributes:
7676
kwargs.setdefault("hue", "scenario")
7777

78-
kwargs.setdefault("ci", "sd")
78+
kwargs.setdefault("errorbar", "sd")
7979
kwargs.setdefault("estimator", np.median)
8080

8181
ax = sns.lineplot(data=plt_df, **kwargs)

src/scmdata/run.py

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@
5959
from .offsets import generate_range, to_offset
6060
from .ops import inject_ops_methods
6161
from .plotting import inject_plotting_methods
62-
from .pyam_compat import IamDataFrame, LongDatetimeIamDataFrame
6362
from .time import _TARGET_DTYPE, TimePoints, TimeseriesConverter
6463
from .units import UnitConverter
6564

@@ -75,6 +74,8 @@
7574

7675
from scmdata.groupby import RunGroupBy
7776

77+
from .pyam_compat import LongDatetimeIamDataFrame
78+
7879
P = ParamSpec("P")
7980

8081

@@ -513,6 +514,9 @@ def _init_timeseries(
513514
copy_data: bool = False,
514515
**kwargs: Any,
515516
) -> None:
517+
# Lazy load
518+
from .pyam_compat import IamDataFrame
519+
516520
if isinstance(data, np.ndarray):
517521
if columns is None:
518522
raise ValueError("`columns` argument is required")
@@ -871,7 +875,7 @@ def timeseries(
871875
raise NonUniqueMetadataError(_meta)
872876

873877
if time_axis is None:
874-
columns = self._time_points.to_index()
878+
columns = self._time_points.to_index().infer_objects()
875879
elif time_axis == "year":
876880
columns = self._time_points.years()
877881
elif time_axis == "year-month":
@@ -902,8 +906,11 @@ def calc_seconds(x):
902906
if len(np.unique(columns)) != len(columns):
903907
raise ValueError(f"Ambiguous time values with time_axis = '{time_axis}'")
904908

905-
df.columns = pd.Index(columns, name="time")
906909
df.index = pd.MultiIndex.from_frame(_meta)
910+
if isinstance(columns, pd.Index):
911+
df.columns = columns
912+
else:
913+
df.columns = pd.Index(columns, name="time")
907914

908915
if drop_all_nan_times:
909916
df = df.dropna(how="all", axis="columns")
@@ -2366,6 +2373,9 @@ def to_iamdataframe(self) -> LongDatetimeIamDataFrame: # pragma: no cover
23662373
ImportError
23672374
If `pyam <https://github.com/IAMconsortium/pyam>`_ is not installed
23682375
"""
2376+
# Lazy load
2377+
from .pyam_compat import LongDatetimeIamDataFrame
2378+
23692379
if LongDatetimeIamDataFrame is None:
23702380
raise ImportError(
23712381
"pyam is not installed. Features involving IamDataFrame are unavailable"
@@ -2617,9 +2627,10 @@ def run_append( # noqa: PLR0912, PLR0915
26172627
ret._df = pd.concat([ret._df, *to_join_dfs], axis="columns").sort_index()
26182628
ret._time_points = TimePoints(ret._df.index.values)
26192629
ret._df.index = ret._time_points.to_index()
2620-
ret._meta = pd.MultiIndex.from_frame(
2621-
pd.concat([ret._meta.to_frame(), *to_join_metas]).astype("category")
2622-
)
2630+
if not all(m.empty for m in to_join_metas):
2631+
ret._meta = pd.MultiIndex.from_frame(
2632+
pd.concat([ret._meta.to_frame(), *to_join_metas]).astype("category")
2633+
)
26232634

26242635
if ret._duplicated_meta():
26252636
if overlapping_times and duplicate_msg:

tests/integration/test_plotting_integration.py

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ def test_plumeplot_pre_calculated_no_plume_for_one_no_median_for_other_different
162162
style_var="climate_model",
163163
)
164164

165-
assert len(record) == 3
165+
assert len(record) == 3, record
166166
assert (
167167
record[0].message.args[0]
168168
== "Quantile 0.05 not available for a_scenario a_model"
@@ -202,19 +202,12 @@ def test_plumeplot_non_unique_lines(plumeplot_scmrun):
202202

203203
error_msg = re.escape(
204204
"More than one timeseries for "
205-
"quantile: {}, "
206-
"scenario: {}, "
207-
"variable: {}.\n"
205+
f"quantile: {quantile}, "
206+
f"scenario: {scenario}, "
207+
f"variable: {variable}.\n"
208208
"Please process your data to create unique quantile timeseries "
209209
"before calling :meth:`plumeplot`.\n"
210-
"Found: {}".format(
211-
quantile,
212-
scenario,
213-
variable,
214-
summary_stats.filter(
215-
quantile=quantile, scenario=scenario, variable=variable
216-
),
217-
)
210+
f"Found: {summary_stats.filter(quantile=quantile, scenario=scenario, variable=variable)}"
218211
)
219212
with pytest.raises(ValueError, match=error_msg):
220213
summary_stats.plumeplot(pre_calculated=True)

tests/unit/test_plotting.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,12 @@ def test_lineplot(mock_long_data, mock_seaborn_lineplot, scm_run):
7474
mock_long_data.assert_called_with(time_axis="year")
7575

7676
mock_seaborn_lineplot.assert_called_with(
77-
ci="sd", data=trv, estimator=np.median, hue="scenario", x="time", y="value"
77+
errorbar="sd",
78+
data=trv,
79+
estimator=np.median,
80+
hue="scenario",
81+
x="time",
82+
y="value",
7883
)
7984

8085

@@ -85,7 +90,7 @@ def test_lineplot_kwargs(mock_long_data, mock_seaborn_lineplot, scm_run):
8590
"x": "x",
8691
"y": "y",
8792
"hue": "hue",
88-
"ci": "ci",
93+
"errorbar": "errorbar",
8994
"estimator": "estimator",
9095
}
9196
trv = "test long_data return value"

tests/unit/test_pyam_compat.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import re
2-
from unittest import mock
32

43
import pandas as pd
54
import pytest
@@ -28,9 +27,3 @@ def test_to_int_value_error(test_iam_df):
2827

2928
with pytest.raises(ValueError, match=error_msg):
3029
LongDatetimeIamDataFrame(idf)
31-
32-
33-
@mock.patch("scmdata.run.LongDatetimeIamDataFrame", None)
34-
def test_pyam_missing(scm_run):
35-
with pytest.raises(ImportError):
36-
scm_run.to_iamdataframe()

tests/unit/test_run.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2031,7 +2031,7 @@ def test_append_duplicate_times(test_append_scm_runs, duplicate_msg):
20312031
"Duplicate time points detected, the output will be the average of "
20322032
"the duplicates. Set `duplicate_msg=False` to silence this message."
20332033
)
2034-
assert len(mock_warn_taking_average) == 1
2034+
assert len(mock_warn_taking_average) == 1, mock_warn_taking_average
20352035
assert str(mock_warn_taking_average[0].message) == warn_msg
20362036
else:
20372037
assert not mock_warn_taking_average
@@ -2050,7 +2050,7 @@ def test_append_doesnt_warn_if_continuous_times(test_append_scm_runs):
20502050
with warnings.catch_warnings(record=True) as mock_warn_taking_average:
20512051
base.append(other)
20522052

2053-
assert len(mock_warn_taking_average) == 0
2053+
assert len(mock_warn_taking_average) == 0, mock_warn_taking_average
20542054

20552055

20562056
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
@@ -3571,7 +3571,7 @@ def test_lineplot_time_axis(scm_run, time_axis, mod_func):
35713571
x="time",
35723572
y="value",
35733573
estimator=np.median,
3574-
ci="sd",
3574+
errorbar="sd",
35753575
hue="scenario",
35763576
other_kwarg="value",
35773577
data=mock_return,

0 commit comments

Comments
 (0)