@@ -490,92 +490,61 @@ def test_setitem_enlargement_keep_index_names(self):
490490 )
491491 tm .assert_frame_equal (df , expected )
492492
493- def test_setitem_enlargement_with_none_key (self ):
493+ def test_setitem_enlargement_multiindex_with_none (self ):
494494 # GH#59153
495- # Test basic enlargement with None keys in different levels
495+ # Test that we can enlarge a DataFrame with a MultiIndex
496+ # when one or more level keys are None
496497 index = MultiIndex .from_tuples (
497498 [("A" , "a1" ), ("A" , "a2" ), ("B" , "b1" ), ("B" , None )]
498499 )
499500 df = DataFrame ([(0 , 6 ), (1 , 5 ), (2 , 4 ), (3 , 7 )], index = index )
500501
501- # Enlarge with None in second level
502+ # Enlarge with a new index entry where one key is None
502503 df .loc [("A" , None ), :] = [12 , 13 ]
504+
503505 expected_index = MultiIndex .from_tuples (
504- [
505- ("A" , "a1" ),
506- ("A" , "a2" ),
507- ("B" , "b1" ),
508- ("B" , None ),
509- ("A" , None ),
510- ]
506+ [("A" , "a1" ), ("A" , "a2" ), ("B" , "b1" ), ("B" , None ), ("A" , None )]
511507 )
512508 expected = DataFrame (
513509 [[0 , 6 ], [1 , 5 ], [2 , 4 ], [3 , 7 ], [12 , 13 ]],
514510 index = expected_index ,
511+ columns = [0 , 1 ],
515512 )
516513 tm .assert_frame_equal (df , expected )
517514
518- # Enlarge with None in first level
519- df .loc [(None , "c1" ), :] = [14 , 15 ]
515+ # Test retrieval of the newly added row
516+ result = df .loc [("A" , None ), :]
517+ expected_row = Series ([12 , 13 ], index = [0 , 1 ], name = ("A" , np .nan ))
518+ tm .assert_series_equal (result , expected_row )
519+
520+ def test_setitem_enlargement_multiindex_multiple_none (self ):
521+ # GH#59153
522+ # Test enlarging with multiple None keys in different levels
523+ index = MultiIndex .from_tuples ([("A" , "a1" ), ("B" , "b1" )])
524+ df = DataFrame ([[1 , 2 ], [3 , 4 ]], index = index , columns = ["x" , "y" ])
525+
526+ # Add row with None in first level
527+ df .loc [(None , "c1" ), :] = [5 , 6 ]
528+
529+ # Add row with None in second level
530+ df .loc [("C" , None ), :] = [7 , 8 ]
531+
532+ # (None, None) case removed as requested
520533 expected_index = MultiIndex .from_tuples (
521534 [
522535 ("A" , "a1" ),
523- ("A" , "a2" ),
524536 ("B" , "b1" ),
525- ("B" , None ),
526- ("A" , None ),
527537 (None , "c1" ),
538+ ("C" , None ),
528539 ]
529540 )
530541 expected = DataFrame (
531- [[0 , 6 ], [ 1 , 5 ], [ 2 , 4 ], [3 , 7 ], [12 , 13 ], [14 , 15 ]],
542+ [[1 , 2 ], [3 , 4 ], [5 , 6 ], [7 , 8 ]],
532543 index = expected_index ,
544+ columns = ["x" , "y" ],
533545 )
534546 tm .assert_frame_equal (df , expected )
535547
536- def test_setitem_enlargement_none_key_indexslice_retrieval (self ):
537- # GH#59153
538- # Test IndexSlice functionality and retrieval with None keys
539-
540- # Test IndexSlice selection with None
541- idx = pd .IndexSlice
542- df = DataFrame (
543- [[10 ], [20 ], [30 ]],
544- index = MultiIndex .from_tuples ([("A" , "a1" ), ("B" , None ), ("C" , "c1" )]),
545- columns = ["val" ]
546- )
547-
548- result = df .loc [idx [:, None ], :]
549- expected = DataFrame (
550- [[20 ]],
551- index = MultiIndex .from_tuples ([("B" , None )]),
552- columns = ["val" ],
553- )
554- tm .assert_frame_equal (result , expected )
555-
556- # Enlarge using IndexSlice with None
557- df .loc [idx ["D" , None ], :] = [40 ]
558- assert df .loc [("D" , None ), "val" ] == 40
559-
560- # Test retrieval after enlargement
561- df2 = DataFrame (
562- [[100 , 200 ]],
563- index = MultiIndex .from_tuples ([("A" , "a1" )]),
564- columns = ["col1" , "col2" ]
565- )
566-
567- df2 .loc [("A" , None ), :] = [300 , 400 ]
568-
569- # Retrieve using full tuple key
570- result = df2 .loc [("A" , None ), :]
571- expected = Series ([300 , 400 ], index = ["col1" , "col2" ], name = ("A" , None ))
572- tm .assert_series_equal (result , expected )
573-
574- # Retrieve using xs
575- result_xs = df2 .xs ("A" )
576- assert None in result_xs .index
577- assert result_xs .loc [None , "col1" ] == 300
578-
579548
580549def test_frame_setitem_view_direct (multiindex_dataframe_random_data ):
581550 # this works because we are modifying the underlying array
0 commit comments