27
27
import bigframes .core .guid as guid
28
28
import bigframes .core .indexes as indexes
29
29
import bigframes .core .scalar
30
+ import bigframes .core .window_spec as windows
30
31
import bigframes .dataframe
31
32
import bigframes .dtypes
32
33
import bigframes .exceptions as bfe
@@ -477,6 +478,19 @@ def _iloc_getitem_series_or_dataframe(
477
478
Union [bigframes .dataframe .DataFrame , bigframes .series .Series ],
478
479
series_or_dataframe .iloc [0 :0 ],
479
480
)
481
+
482
+ # Check if both positive index and negative index are necessary
483
+ if isinstance (key , (bigframes .series .Series , indexes .Index )):
484
+ # Avoid data download
485
+ is_key_unisigned = False
486
+ else :
487
+ first_sign = key [0 ] >= 0
488
+ is_key_unisigned = True
489
+ for k in key :
490
+ if (k >= 0 ) != first_sign :
491
+ is_key_unisigned = False
492
+ break
493
+
480
494
if isinstance (series_or_dataframe , bigframes .series .Series ):
481
495
original_series_name = series_or_dataframe .name
482
496
series_name = (
@@ -497,7 +511,27 @@ def _iloc_getitem_series_or_dataframe(
497
511
block = df ._block
498
512
# explicitly set index to offsets, reset_index may not generate offsets in some modes
499
513
block , offsets_id = block .promote_offsets ("temp_iloc_offsets_" )
500
- block = block .set_index ([offsets_id ])
514
+ pos_block = block .set_index ([offsets_id ])
515
+
516
+ if not is_key_unisigned or key [0 ] < 0 :
517
+ neg_block , size_col_id = block .apply_window_op (
518
+ offsets_id ,
519
+ ops .aggregations .SizeUnaryOp (),
520
+ window_spec = windows .rows (),
521
+ )
522
+ neg_block , neg_index_id = neg_block .apply_binary_op (
523
+ offsets_id , size_col_id , ops .SubOp ()
524
+ )
525
+
526
+ neg_block = neg_block .set_index ([neg_index_id ]).drop_columns (
527
+ [size_col_id , offsets_id ]
528
+ )
529
+
530
+ if is_key_unisigned :
531
+ block = pos_block if key [0 ] >= 0 else neg_block
532
+ else :
533
+ block = pos_block .concat ([neg_block ], how = "inner" )
534
+
501
535
df = bigframes .dataframe .DataFrame (block )
502
536
503
537
result = df .loc [key ]
0 commit comments