@@ -1065,3 +1065,45 @@ def test_read_sdata(tmp_path: Path, points: SpatialData) -> None:
10651065 assert_spatial_data_objects_are_identical (sdata_from_path , sdata_from_str )
10661066 assert_spatial_data_objects_are_identical (sdata_from_path , sdata_from_upath )
10671067 assert_spatial_data_objects_are_identical (sdata_from_path , sdata_from_zarr_group )
1068+
1069+
1070+ def test_sdata_with_nan_in_obs () -> None :
1071+ """Test writing SpatialData with mixed string/NaN values in obs works correctly.
1072+
1073+ Regression test for https://github.com/scverse/spatialdata/issues/399
1074+ Previously this raised TypeError: expected unicode string, found nan.
1075+ Now the write succeeds, though NaN values in object-dtype columns are
1076+ converted to the string "nan" after round-trip.
1077+ """
1078+ from spatialdata .models import TableModel
1079+
1080+ table = TableModel .parse (
1081+ AnnData (
1082+ obs = pd .DataFrame (
1083+ {
1084+ "region" : ["region1" , "region2" ],
1085+ "instance" : [0 , 0 ],
1086+ "column_only_region1" : ["string" , np .nan ],
1087+ "column_only_region2" : [np .nan , 3 ],
1088+ }
1089+ )
1090+ ),
1091+ region_key = "region" ,
1092+ instance_key = "instance" ,
1093+ region = ["region1" , "region2" ],
1094+ )
1095+ sdata = SpatialData (tables = {"table" : table })
1096+ assert sdata ["table" ].obs ["column_only_region1" ].iloc [1 ] is np .nan
1097+ assert np .isnan (sdata ["table" ].obs ["column_only_region2" ].iloc [0 ])
1098+
1099+ with tempfile .TemporaryDirectory () as tmpdir :
1100+ path = os .path .join (tmpdir , "data.zarr" )
1101+ sdata .write (path )
1102+
1103+ sdata2 = SpatialData .read (path )
1104+ assert "column_only_region1" in sdata2 ["table" ].obs .columns
1105+ assert sdata2 ["table" ].obs ["column_only_region1" ].iloc [0 ] == "string"
1106+ assert sdata2 ["table" ].obs ["column_only_region2" ].iloc [1 ] == 3
1107+ # After round-trip, NaN in object-dtype column becomes string "nan"
1108+ assert sdata2 ["table" ].obs ["column_only_region1" ].iloc [1 ] == "nan"
1109+ assert np .isnan (sdata2 ["table" ].obs ["column_only_region2" ].iloc [0 ])
0 commit comments