Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 55 additions & 2 deletions src/petab_gui/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,38 @@ def redo(self):
if np.any(dtypes != df.dtypes):
for col, dtype in dtypes.items():
if dtype != df.dtypes[col]:
df[col] = df[col].astype(dtype)
is_pandas_nullable_int = isinstance(
dtype,
(
pd.Int64Dtype,
pd.Int32Dtype,
pd.Int16Dtype,
pd.Int8Dtype,
),
)

if is_pandas_nullable_int:
# Keep pandas nullable integer types as is
df[col] = df[col].astype(dtype)
# If column has NaN and dtype is integer, use nullable Int type
elif (
np.issubdtype(dtype, np.integer)
and df[col].isna().any()
):
# Convert numpy int types to pandas nullable Int types
if dtype == np.int64:
df[col] = df[col].astype("Int64")
elif dtype == np.int32:
df[col] = df[col].astype("Int32")
elif dtype == np.int16:
df[col] = df[col].astype("Int16")
elif dtype == np.int8:
df[col] = df[col].astype("Int8")
else:
# Fallback for other integer types
df[col] = df[col].astype("Int64")
else:
df[col] = df[col].astype(dtype)
self.model.endInsertRows()
else:
self.model.beginRemoveRows(
Expand Down Expand Up @@ -261,8 +292,30 @@ def _apply_changes(self, use_new: bool):
for col, dtype in original_dtypes.items():
if col not in update_df.columns:
continue
if np.issubdtype(dtype, np.number):
# Check if it's a pandas extension dtype (like Int64)
is_pandas_nullable_int = isinstance(
dtype,
(pd.Int64Dtype, pd.Int32Dtype, pd.Int16Dtype, pd.Int8Dtype),
)

if is_pandas_nullable_int:
# Keep pandas nullable integer types as is
df[col] = pd.to_numeric(df[col], errors="coerce")
df[col] = df[col].astype(dtype)
elif np.issubdtype(dtype, np.number):
df[col] = pd.to_numeric(df[col], errors="coerce")
# If original dtype was integer and column has NaN, use nullable Int type
if np.issubdtype(dtype, np.integer) and df[col].isna().any():
if dtype == np.int64:
df[col] = df[col].astype("Int64")
elif dtype == np.int32:
df[col] = df[col].astype("Int32")
elif dtype == np.int16:
df[col] = df[col].astype("Int16")
elif dtype == np.int8:
df[col] = df[col].astype("Int8")
else:
df[col] = df[col].astype("Int64")
else:
df[col] = df[col].astype(dtype)

Expand Down