@@ -355,48 +355,53 @@ def len_unique(x):
355355
356356def _id_var (x : AnyArrayLike , drop : bool = False ) -> list [int ]:
357357 """
358- Assign ids to items in x. If two items
359- are the same, they get the same id.
358+ Assign ids to items in x
359+
360+ If two items are the same, they get the same id.
361+ The ids start at 1 and NaNs have the highest id.
360362
361363 Parameters
362364 ----------
363365 x : array_like
364366 items to associate ids with
365367 drop : bool
366368 Whether to drop unused factor levels
369+
370+ Returns
371+ -------
372+ ids:
373+ List of ids
367374 """
368375 if len (x ) == 0 :
369376 return []
370377
371378 if isinstance (x , pd .Series ) and array_kind .categorical (x ):
379+ # The ids are a "re-coding" of the categorical codes/levels
380+ # to meet the output requirements.
372381 if drop :
373382 x = x .cat .remove_unused_categories ()
374- lst = list (x .cat .codes + 1 )
375- if 0 in lst :
376- new_nan_code = max (lst ) + 1
377- lst = [val if val != 0 else new_nan_code for val in lst ]
378- else :
379- has_nan = any (np .isnan (i ) for i in x if isinstance (i , float ))
380- if has_nan :
381- # NaNs are -1, we give them the highest code
382- nan_code = - 1
383- new_nan_code = np .max (x .cat .codes ) + 1
384- # TODO: We are assuming that x is of type Sequence[int|nan]
385- # is that accurate.
386- lst = [val if val != nan_code else new_nan_code for val in x ]
387- else :
388- lst = list (x .cat .codes + 1 )
383+
384+ codes = x .cat .codes
385+
386+ # We want our list to start at 1
387+ # But NaNs are -1, and if we have them we want them to have,
388+ # the highest code. i.e. to be ordered last.
389+ ids = list (codes + 1 )
390+ has_nan = min (codes ) == - 1
391+ if has_nan :
392+ # The NaNs now have an id of 0
393+ highest_id = max (ids ) + 1
394+ ids = [highest_id if i == 0 else i for i in ids ]
389395 else :
390396 try :
391397 levels = sorted (set (x ))
392398 except TypeError :
393399 # x probably has NANs
394400 levels = multitype_sort (list (set (x )))
395401
396- lst = match (x , levels )
397- lst = [item + 1 for item in lst ]
402+ ids = list (match (x , levels , start = 1 ))
398403
399- return lst
404+ return ids
400405
401406
402407def join_keys (x , y , by = None ):
0 commit comments