@@ -857,3 +857,55 @@ def test_dtype_representation(using_infer_string):
857857 dtype = object ,
858858 )
859859 tm .assert_series_equal (result , expected )
860+
861+
862+ def test_from_tuples_different_lengths_gh60695 ():
863+ """
864+ Test that MultiIndex.from_tuples properly handles tuples of different lengths.
865+
866+ GH#60695
867+ """
868+ # Test case 1: Original issue example
869+ tuples = [("l1" ,), ("l1" , "l2" )]
870+ result = pd .MultiIndex .from_tuples (tuples )
871+ expected = pd .MultiIndex .from_tuples ([("l1" , np .nan ), ("l1" , "l2" )])
872+ tm .assert_index_equal (result , expected )
873+
874+ # Test case 2: Series construction with tuple keys
875+ s = pd .Series ({("l1" ,): "v1" , ("l1" , "l2" ): "v2" })
876+ expected = pd .Series (
877+ ["v1" , "v2" ],
878+ index = pd .MultiIndex .from_tuples ([("l1" , np .nan ), ("l1" , "l2" )])
879+ )
880+ tm .assert_series_equal (s , expected )
881+
882+ # Test case 3: Multiple levels with None
883+ data = {(1 , 1 , None ): - 1.0 }
884+ result = pd .Series (data )
885+ expected = pd .Series (
886+ - 1.0 ,
887+ index = pd .MultiIndex .from_tuples ([(1 , 1 , np .nan )]),
888+ )
889+ tm .assert_series_equal (result , expected )
890+
891+ # Test case 4: Mixed length tuples
892+ tuples = [("a" ,), ("b" , "c" ), ("d" , "e" , "f" )]
893+ result = pd .MultiIndex .from_tuples (tuples )
894+ expected = pd .MultiIndex .from_tuples ([
895+ ("a" , np .nan , np .nan ),
896+ ("b" , "c" , np .nan ),
897+ ("d" , "e" , "f" )
898+ ])
899+ tm .assert_index_equal (result , expected )
900+
901+ # Test case 5: DataFrame with tuple index
902+ df = pd .DataFrame (
903+ {"col" : ["v1" , "v2" ]},
904+ index = pd .MultiIndex .from_tuples ([("l1" ,), ("l1" , "l2" )])
905+ )
906+ expected_index = pd .MultiIndex .from_tuples ([("l1" , np .nan ), ("l1" , "l2" )])
907+ expected_df = pd .DataFrame (
908+ {"col" : ["v1" , "v2" ]},
909+ index = expected_index
910+ )
911+ tm .assert_frame_equal (df , expected_df )
0 commit comments