code: def hash_array(vals, encoding="utf8", hash_key=None, categorize=True):
      """
      Given a 1d array, return an array of deterministic integers.
  
      .. versionadded:: 0.19.2
  
      Parameters
      ----------
      vals : ndarray, Categorical
      encoding : string, default 'utf8'
          encoding for data & key when strings
      hash_key : string key to encode, default to _default_hash_key
      categorize : bool, default True
          Whether to first categorize object arrays before hashing. This is more
          efficient when the array contains duplicate values.
  
          .. versionadded:: 0.20.0
  
      Returns
      -------
      1d uint64 numpy array of hash values, same length as the vals
      """
  
      if not hasattr(vals, "dtype"):
          raise TypeError("must pass a ndarray-like")
      dtype = vals.dtype
  
      if hash_key is None:
          hash_key = _default_hash_key
  
      # For categoricals, we hash the categories, then remap the codes to the
      # hash values. (This check is above the complex check so that we don't ask
      # numpy if categorical is a subdtype of complex, as it will choke).
      if is_categorical_dtype(dtype):
          return _hash_categorical(vals, encoding, hash_key)
      elif is_extension_array_dtype(dtype):
          vals, _ = vals._values_for_factorize()
          dtype = vals.dtype
  
      # we'll be working with everything as 64-bit values, so handle this
      # 128-bit value early
      if np.issubdtype(dtype, np.complex128):
          return hash_array(vals.real) + 23 * hash_array(vals.imag)
  
      # First, turn whatever array this is into unsigned 64-bit ints, if we can
      # manage it.
      elif isinstance(dtype, np.bool):
          vals = vals.astype("u8")
      elif issubclass(dtype.type, (np.datetime64, np.timedelta64)):
          vals = vals.view("i8").astype("u8", copy=False)
      elif issubclass(dtype.type, np.number) and dtype.itemsize <= 8:
          vals = vals.view("u{}".format(vals.dtype.itemsize)).astype(
              "u8"
          )
      else:
          # With repeated values, its MUCH faster to categorize object dtypes,
          # then hash and rename categories. We allow skipping the categorization
          # when the values are known/likely to be unique.
          if categorize:
              from pandas import factorize, Categorical, Index
  
              codes, categories = factorize(vals, sort=False)
              cat = Categorical(
                  codes, Index(categories), ordered=False, fastpath=True
              )
              return _hash_categorical(cat, encoding, hash_key)
  
          try:
              vals = hashing.hash_object_array(vals, hash_key, encoding)
          except TypeError:
              # we have mixed types
              vals = hashing.hash_object_array(
                  vals.astype(str).astype(object), hash_key, encoding
              )
  
      # Then, redistribute these 64-bit ints within the space of 64-bit ints
      vals ^= vals >> 30
      vals *= np.uint64(0xBF58476D1CE4E5B9)
      vals ^= vals >> 27
      vals *= np.uint64(0x94D049BB133111EB)
      vals ^= vals >> 31
      return vals
  
file_path: catboost/contrib/python/pandas/py2/pandas/core/util/hashing.py
imports: import itertools
  import numpy
  from pandas._libs import hashing, tslibs
  from pandas.core.dtypes.cast import infer_dtype_from_scalar
  from pandas.core.dtypes.common import is_categorical_dtype, is_extension_array_dtype, is_list_like
  from pandas.core.dtypes.generic import ABCDataFrame, ABCIndexClass, ABCMultiIndex, ABCSeries
  from pandas.core.dtypes.missing import isna
label_desc: Use image node_id 6 for calling a global function with example usage: hash_array(vals, encoding, hash_key, categorize) and returns: vals, _hash_categorical, unknown, _hash_categorical