@@ -392,6 +392,73 @@ def _from_sequence_of_strings(
392
392
)
393
393
return cls ._from_sequence (scalars , dtype = pa_type , copy = copy )
394
394
395
+ def _cast_pointwise_result (self , values ) -> ArrayLike :
396
+ if len (values ) == 0 :
397
+ # Retain our dtype
398
+ return self [:0 ].copy ()
399
+
400
+ try :
401
+ arr = pa .array (values , from_pandas = True )
402
+ except (ValueError , TypeError ):
403
+ # e.g. test_by_column_values_with_same_starting_value with nested
404
+ # values, one entry of which is an ArrowStringArray
405
+ # or test_agg_lambda_complex128_dtype_conversion for complex values
406
+ return super ()._cast_pointwise_result (values )
407
+
408
+ if pa .types .is_duration (arr .type ):
409
+ # workaround for https://github.com/apache/arrow/issues/40620
410
+ result = ArrowExtensionArray ._from_sequence (values )
411
+ if pa .types .is_duration (self ._pa_array .type ):
412
+ result = result .astype (self .dtype ) # type: ignore[assignment]
413
+ elif pa .types .is_timestamp (self ._pa_array .type ):
414
+ # Try to retain original unit
415
+ new_dtype = ArrowDtype (pa .duration (self ._pa_array .type .unit ))
416
+ try :
417
+ result = result .astype (new_dtype ) # type: ignore[assignment]
418
+ except ValueError :
419
+ pass
420
+ elif pa .types .is_date64 (self ._pa_array .type ):
421
+ # Try to match unit we get on non-pointwise op
422
+ dtype = ArrowDtype (pa .duration ("ms" ))
423
+ result = result .astype (dtype ) # type: ignore[assignment]
424
+ elif pa .types .is_date (self ._pa_array .type ):
425
+ # Try to match unit we get on non-pointwise op
426
+ dtype = ArrowDtype (pa .duration ("s" ))
427
+ result = result .astype (dtype ) # type: ignore[assignment]
428
+ return result
429
+
430
+ elif pa .types .is_date (arr .type ) and pa .types .is_date (self ._pa_array .type ):
431
+ arr = arr .cast (self ._pa_array .type )
432
+ elif pa .types .is_time (arr .type ) and pa .types .is_time (self ._pa_array .type ):
433
+ arr = arr .cast (self ._pa_array .type )
434
+ elif pa .types .is_decimal (arr .type ) and pa .types .is_decimal (self ._pa_array .type ):
435
+ arr = arr .cast (self ._pa_array .type )
436
+ elif pa .types .is_integer (arr .type ) and pa .types .is_integer (self ._pa_array .type ):
437
+ try :
438
+ arr = arr .cast (self ._pa_array .type )
439
+ except pa .lib .ArrowInvalid :
440
+ # e.g. test_combine_add if we can't cast
441
+ pass
442
+ elif pa .types .is_floating (arr .type ) and pa .types .is_floating (
443
+ self ._pa_array .type
444
+ ):
445
+ try :
446
+ arr = arr .cast (self ._pa_array .type )
447
+ except pa .lib .ArrowInvalid :
448
+ # e.g. test_combine_add if we can't cast
449
+ pass
450
+
451
+ if isinstance (self .dtype , StringDtype ):
452
+ if pa .types .is_string (arr .type ) or pa .types .is_large_string (arr .type ):
453
+ # ArrowStringArrayNumpySemantics
454
+ return type (self )(arr ).astype (self .dtype )
455
+ if self .dtype .na_value is np .nan :
456
+ # ArrowEA has different semantics, so we return numpy-based
457
+ # result instead
458
+ return super ()._cast_pointwise_result (values )
459
+ return ArrowExtensionArray (arr )
460
+ return type (self )(arr )
461
+
395
462
@classmethod
396
463
def _box_pa (
397
464
cls , value , pa_type : pa .DataType | None = None
0 commit comments