Skip to content

Commit 2ac89a2

Browse files
authored
chore(dependencies): support pandas 3 (#2723)
Recently pandas 3 was released. Only minimal changes needed from us, namely * switching timedelta units from deprecated "d" to "D" * a fix in the model splitter where columns that were previously renamed automatically on dataframe construction must now be renamed manually due to stricter dataframe init method requirements There are two other potentially relevant changes * String dtype Pandas 3 will infer string columns as str dtype instead of object. Code checking dtype == 'object' for strings will break. I think we are safe as internal dtype checks are generally on numpy arrays, not pandas DataFrames. We kind of luck out for having not migrated everything over to pandas. When we do pd.DataFrame.from_records(recarray), numpy string fields will get converted to str dtype instead of object. But I don't think we need to care, indexing, selection, etc should all work as before. * Copy-on-Write (CoW) As far as I can tell we use .loc internally, no chained assignments, so we should be good.
1 parent ef59774 commit 2ac89a2

4 files changed

Lines changed: 17 additions & 13 deletions

File tree

flopy/export/metadata.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ def time_coverage(self):
188188
mlen = self.model_time.perlen.sum()
189189
tunits = self.model_time.time_units
190190
tc["duration"] = f"{mlen} {tunits}"
191-
end = strt + pd.Timedelta(mlen, unit="d")
191+
end = strt + pd.Timedelta(mlen, unit="D")
192192
tc["end"] = str(end)
193193
return tc
194194

flopy/mf6/data/mfdataplist.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -676,9 +676,11 @@ def set_data(self, data, autofill=False, check_data=True, append=False):
676676
if len(data[0]) == len(self._data_item_names):
677677
# data most likely being stored with cellids as tuples,
678678
# create a dataframe and untuple the cellids
679-
data = pandas.DataFrame(
680-
data, columns=self._data_item_names
681-
)
679+
# In pandas 3+, DataFrame() with recarray requires columns to match
680+
# field names, so create without columns param then rename if needed
681+
data = pandas.DataFrame(data)
682+
if list(data.columns) != self._data_item_names:
683+
data.columns = self._data_item_names
682684
data = self._untuple_cellids(data)[0]
683685
# make sure columns are still in correct order
684686
data = pandas.DataFrame(data, columns=self._header_names)
@@ -691,19 +693,21 @@ def set_data(self, data, autofill=False, check_data=True, append=False):
691693
else:
692694
# data size matches the expected header names, create a pandas
693695
# dataframe from the data
694-
data_new = pandas.DataFrame(data, columns=self._header_names)
696+
# In pandas 3+, DataFrame() with recarray requires columns to match
697+
# field names, so create without columns param then rename if needed
698+
data_new = pandas.DataFrame(data)
699+
if list(data_new.columns) != self._header_names:
700+
data_new.columns = self._header_names
695701
if not self._dataframe_check(data_new):
696702
data_list = self._untuple_recarray(data)
697-
data = pandas.DataFrame(
698-
data_list, columns=self._header_names
699-
)
703+
data = pandas.DataFrame(data_list)
704+
if list(data.columns) != self._header_names:
705+
data.columns = self._header_names
700706
else:
701707
data, count = self._untuple_cellids(data_new)
702708
if count > 0:
703709
# make sure columns are still in correct order
704-
data = pandas.DataFrame(
705-
data, columns=self._header_names
706-
)
710+
data = pandas.DataFrame(data, columns=self._header_names)
707711
elif isinstance(data, list) or isinstance(data, tuple):
708712
if not (isinstance(data[0], list) or isinstance(data[0], tuple)):
709713
# get data in the format of a tuple of lists (or tuples)

flopy/utils/mtlistfile.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def __init__(self, file_name):
5151

5252
return
5353

54-
def parse(self, forgive=True, diff=True, start_datetime=None, time_unit="d"):
54+
def parse(self, forgive=True, diff=True, start_datetime=None, time_unit="D"):
5555
"""
5656
Main entry point for parsing the list file.
5757

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ requires-python = ">=3.10"
2828
dependencies = [
2929
"numpy>=1.20.3,<3.0",
3030
"matplotlib >=1.4.0",
31-
"pandas >=2.0.0,<3.0",
31+
"pandas >=2.0.0",
3232
]
3333
dynamic = ["version", "readme"]
3434

0 commit comments

Comments
 (0)