Repository: modflowpy/flopy

Issue:
feat: support kper column in stress period recarray/dataframe input data
I like the idea of a kper column in the dataframe/recarray.  We have been kicking that idea around for a while now and should see what it would take to support.

_Originally posted by @langevin-usgs in https://github.com/modflowpy/flopy/discussions/2135#discussioncomment-9021953_

Discussion:

Patch:
diff --git a/flopy/utils/util_list.py b/flopy/utils/util_list.py
index 62fdb5ef..66d2baf3 100644
--- a/flopy/utils/util_list.py
+++ b/flopy/utils/util_list.py
@@ -296,6 +296,16 @@ class MfList(DataInterface, DataListInterface):
             fmt_string = "".join(fmts)
         return fmt_string
 
+    def __cast_tabular(self, data):
+        data = pd.DataFrame(data)
+        if "kper" in data.dtypes:
+            groups = data.groupby("kper")
+            data = {kper: group.drop("kper", axis=1) for kper, group in groups}
+            for kper, d in data.items():
+                self.__cast_dataframe(kper, d)
+        else:
+            self.__cast_dataframe(0, data)
+
     # Private method to cast the data argument
     # Should only be called by the constructor
     def __cast_data(self, data):
@@ -350,15 +360,18 @@ class MfList(DataInterface, DataListInterface):
                         f"{type(d)} at kper {kper}"
                     )
 
-        # A single recarray - same MfList for all stress periods
+        # A single dataframe
+        elif isinstance(data, pd.DataFrame):
+            self.__cast_tabular(data)
+
+        # A single recarray
         elif isinstance(data, np.recarray):
-            self.__cast_recarray(0, data)
+            self.__cast_tabular(data)
+
         # A single ndarray
         elif isinstance(data, np.ndarray):
             self.__cast_ndarray(0, data)
-        # A single dataframe
-        elif isinstance(data, pd.DataFrame):
-            self.__cast_dataframe(0, data)
+
         # A single filename
         elif isinstance(data, str):
             self.__cast_str(0, data)


Test patch:
diff --git a/autotest/test_modflow.py b/autotest/test_modflow.py
index b0127aaf..c421869d 100644
--- a/autotest/test_modflow.py
+++ b/autotest/test_modflow.py
@@ -917,17 +917,12 @@ def test_bcs_check(function_tmpdir):
     ghb = ModflowGhb(mf, stress_period_data={0: [0, 0, 0, 100, 1]})
     riv_spd = pd.DataFrame(
         [[0, 0, 0, 0, 101.0, 10.0, 100.0], [0, 0, 0, 1, 80.0, 10.0, 90.0]],
-        columns=["per", "k", "i", "j", "stage", "cond", "rbot"],
+        columns=["kper", "k", "i", "j", "stage", "cond", "rbot"],
     )
 
-    pers = riv_spd.groupby("per")
-    riv_spd = {i: pers.get_group(i).drop("per", axis=1) for i in [0]}
     riv = ModflowRiv(
         mf,
-        stress_period_data=riv_spd,
-        # stress_period_data={
-        #     0: [[0, 0, 0, 101, 10, 100], [0, 0, 1, 80, 10, 90]]
-        # },
+        stress_period_data=riv_spd.to_records(index=False),
     )
     chk = ghb.check()
     assert chk.summary_array["desc"][0] == "BC in inactive cell"