Skip to content

Commit e16bac7

Browse files
committed
MAINT: Add NumPy 2 Compat
1 parent 285e6f4 commit e16bac7

File tree

12 files changed

+51
-15
lines changed

12 files changed

+51
-15
lines changed

azure-pipelines.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ variables:
1010
VML_NUM_THREADS: 1
1111
OPENBLAS_NUM_THREADS: 1
1212
PYTHONHASHSEED: 12345678 # Ensure tests are correctly gathered by xdist
13-
SETUPTOOLS_USE_DISTUTILS: "stdlib"
1413
TEST_INSTALL: false
1514
MPLBACKEND: agg
1615
coverage: true

ci/azure_template_posix.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,16 @@ jobs:
6060
python311_latest:
6161
python.version: '3.11'
6262
XXHASH: true
63-
python311_copy_on_write:
64-
python.version: '3.11'
63+
python312_latest:
64+
python.version: '3.12'
65+
XXHASH: true
66+
python312_copy_on_write:
67+
python.version: '3.12'
6568
XXHASH: true
6669
LM_TEST_COPY_ON_WRITE: 1
70+
python312_pre:
71+
python.version: '3.12'
72+
PIP_PRE: true
6773
maxParallel: 10
6874

6975
steps:

ci/install-posix.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,9 @@ if [[ -n ${FORMULAIC} ]]; then CMD="$CMD formulaic~=${FORMULAIC}"; fi
1313
if [[ -n ${XXHASH} ]]; then CMD="$CMD xxhash"; fi
1414
echo "$CMD"
1515
eval "$CMD"
16+
17+
if [ "${PIP_PRE}" = true ]; then
18+
python -m pip uninstall -y numpy pandas scipy matplotlib statsmodels
19+
python -m pip install -i https://pypi.anaconda.org/scientific-python-nightly-wheels/simple numpy pandas scipy matplotlib --upgrade --use-deprecated=legacy-resolver
20+
python -m pip install git+https://github.com/statsmodels/statsmodels.git --upgrade --no-build-isolation -v
21+
fi

linearmodels/compat/pandas.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from packaging.version import parse
2+
import pandas as pd
3+
4+
PANDAS_VERSION = parse(pd.__version__)
5+
PD_GTE_21 = not (PANDAS_VERSION <= parse("2.0.99"))
6+
PD_LT_22 = PANDAS_VERSION <= parse("2.1.99")
7+
ANNUAL_FREQ = "A-DEC" if PD_LT_22 else "YE-DEC"
8+
9+
__all__ = ["ANNUAL_FREQ", "PD_GTE_21", "PD_LT_22"]

linearmodels/iv/results.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -764,7 +764,11 @@ def diagnostics(self) -> DataFrame:
764764
]
765765
out_df = out_df[cols]
766766
for col in out_df:
767-
out_df[col] = to_numeric(out_df[col], errors="ignore")
767+
try:
768+
out_df[col] = to_numeric(out_df[col])
769+
except ValueError:
770+
# If an error is raised, ignore and keep the column
771+
pass
768772

769773
return out_df
770774

linearmodels/panel/data.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from __future__ import annotations
22

3+
from linearmodels.compat.pandas import PD_GTE_21
4+
35
from collections.abc import Hashable, Sequence
46
from itertools import product
57
from typing import Literal, Union, cast, overload
@@ -227,7 +229,8 @@ def __init__(
227229
if copy:
228230
self._frame = self._frame.copy()
229231
else:
230-
self._frame = DataFrame({var_name: x.T.stack(dropna=False)})
232+
options = {"future_stack": True} if PD_GTE_21 else {"dropna": False}
233+
self._frame = DataFrame({var_name: x.T.stack(**options)})
231234
elif isinstance(x, np.ndarray):
232235
if x.ndim not in (2, 3):
233236
raise ValueError("2 or 3-d array required for numpy input")
@@ -298,6 +301,8 @@ def drop(self, locs: Series | BoolArray) -> None:
298301
Boolean array indicating observations to drop with reference to
299302
the dataframe view of the data
300303
"""
304+
if isinstance(locs, Series):
305+
locs = np.asarray(locs)
301306
self._frame = self._frame.loc[~locs.ravel()]
302307
self._frame = self._minimize_multiindex(self._frame)
303308
# Reset panel and shape after a drop

linearmodels/panel/utility.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from __future__ import annotations
22

3+
from linearmodels.compat.pandas import ANNUAL_FREQ
4+
35
from collections import defaultdict
46
from typing import NamedTuple, TypeVar, cast
57

@@ -613,7 +615,7 @@ def generate_panel_data(
613615
x.flat[locs] = np.nan
614616

615617
entities = [f"firm{i}" for i in range(n)]
616-
time = [dt for dt in date_range("1-1-1900", periods=t, freq="A-DEC")]
618+
time = [dt for dt in date_range("1-1-1900", periods=t, freq=ANNUAL_FREQ)]
617619
var_names = [f"x{i}" for i in range(k)]
618620
if const:
619621
var_names[1:] = var_names[:-1]

linearmodels/shared/hypotheses.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -117,13 +117,13 @@ class InvalidTestStatistic(WaldTestStatistic):
117117

118118
def __init__(self, reason: str, *, name: str | None = None) -> None:
119119
self._reason = reason
120-
super().__init__(np.NaN, "", df=1, df_denom=1, name=name)
120+
super().__init__(np.nan, "", df=1, df_denom=1, name=name)
121121
self.dist_name = "None"
122122

123123
@property
124124
def pval(self) -> float:
125-
"""Always returns np.NaN"""
126-
return np.NaN
125+
"""Always returns np.nan"""
126+
return np.nan
127127

128128
@property
129129
def critical_values(self) -> None:
@@ -158,13 +158,13 @@ def __init__(self, *, reason: str | None = None, name: str | None = None):
158158
if reason is None:
159159
self._reason = "Test is not applicable to model specification"
160160

161-
super().__init__(np.NaN, "", df=1, df_denom=1, name=name)
161+
super().__init__(np.nan, "", df=1, df_denom=1, name=name)
162162
self.dist_name = "None"
163163

164164
@property
165165
def pval(self) -> float:
166-
"""Always returns np.NaN"""
167-
return np.NaN
166+
"""Always returns np.nan"""
167+
return np.nan
168168

169169
@property
170170
def critical_values(self) -> None:

linearmodels/tests/panel/_utility.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
from __future__ import annotations
22

3+
from linearmodels.compat.pandas import ANNUAL_FREQ
4+
35
from typing import Literal
46

57
import numpy as np
@@ -121,7 +123,7 @@ def generate_data(
121123
return AttrDict(y=y, x=x, w=w, c=c, vc1=vc1, vc2=vc2)
122124

123125
entities = ["firm" + str(i) for i in range(n)]
124-
time = date_range("1-1-1900", periods=t, freq="A-DEC")
126+
time = date_range("1-1-1900", periods=t, freq=ANNUAL_FREQ)
125127
var_names = ["x" + str(i) for i in range(k)]
126128
# y = DataFrame(y, index=time, columns=entities)
127129
y_df = panel_to_frame(

linearmodels/tests/shared/test_utility.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from linearmodels.compat.pandas import ANNUAL_FREQ
2+
13
import pickle
24
import random
35
import string
@@ -224,7 +226,7 @@ def test_panel_to_midf():
224226
],
225227
)
226228
)
227-
times = pd.date_range("1999-12-31", freq="A-DEC", periods=7)
229+
times = pd.date_range("1999-12-31", freq=ANNUAL_FREQ, periods=7)
228230
var_names = [f"x.{i}" for i in range(1, 4)]
229231
df3 = panel_to_frame(x, var_names, times, entities, True)
230232
mi = pd.MultiIndex.from_product([times, entities])

0 commit comments

Comments
 (0)