diff --git a/pandas/core/ops/array_ops.py b/pandas/core/ops/array_ops.py index 983a3df57e369..bed413d1f4d68 100644 --- a/pandas/core/ops/array_ops.py +++ b/pandas/core/ops/array_ops.py @@ -57,7 +57,8 @@ from pandas.core.ops import missing from pandas.core.ops.dispatch import should_extension_dispatch from pandas.core.ops.invalid import invalid_comparison - +from pandas.core.frame import DataFrame +from pandas.core.series import Series if TYPE_CHECKING: from pandas._typing import ( ArrayLike, @@ -405,6 +406,25 @@ def logical_op(left: ArrayLike, right: Any, op) -> ArrayLike: ------- ndarray or ExtensionArray """ + def logical_operator(left: ArrayLike, right: Any, op) -> ArrayLike: + # Check if `right` is a Series and `left` is a DataFrame, and apply broadcasting + if isinstance(left, DataFrame) and isinstance(right, Series): + right = right.values # Convert Series to array for broadcasting + + # Convert right to a scalar or valid object if necessary + right = lib.item_from_zerodim(right) + + # Check for dtype-less sequences (e.g., list, tuple) and raise error + if is_list_like(right) and not hasattr(right, "dtype"): + # Raise an error if `right` is a list or tuple without a dtype + raise TypeError( + "Logical ops (and, or, xor) between Pandas objects and dtype-less " + "sequences (e.g., list, tuple) are no longer supported. " + "Wrap the object in a Series, Index, or np.array before operating." + ) + + # Proceed with the logical operation + return logical_operator(op(left, right)) def fill_bool(x, left=None): # if `left` is specifically not-boolean, we do not cast to bool diff --git a/pandas/core/series.py b/pandas/core/series.py index 35b576da87ed7..677822b153cc7 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -3233,6 +3233,13 @@ def combine_first(self, other) -> Series: """ from pandas.core.reshape.concat import concat + def replace_none_with_nan(series): + series.fillna(value=np.nan, inplace=True) + + """Apply the function to both Series""" + replace_none_with_nan(self) + replace_none_with_nan(other) + if self.dtype == other.dtype: if self.index.equals(other.index): return self.mask(self.isna(), other) diff --git a/pandas/io/parsers/arrow_parser_wrapper.py b/pandas/io/parsers/arrow_parser_wrapper.py index 672672490996d..5e774035be7a1 100644 --- a/pandas/io/parsers/arrow_parser_wrapper.py +++ b/pandas/io/parsers/arrow_parser_wrapper.py @@ -268,6 +268,14 @@ def read(self) -> DataFrame: dtype_backend = self.kwds["dtype_backend"] + # Handle missing date values by checking for timestamp columns + for i, field in enumerate(table.schema): + if pa.types.is_timestamp(field.type): + column = table.column(i).to_pandas() + column.fillna(pd.NaT, inplace=True) + + table = table.set_column(i, field.name, pa.array(column)) + # Convert all pa.null() cols -> float64 (non nullable) # else Int64 (nullable case, see below) if dtype_backend is lib.no_default: