code: 
  
  
  import warnings
  
  import numpy as np
  import pandas as pd
  from matplotlib import pyplot as plt
  from sklearn.metrics import pairwise_distances
  
  warnings.filterwarnings("ignore")
  
  _SCREAMING_SNAKE_CASE    :				Optional[int]       =					"""K-MEANS-CLUST/ """
  def     UpperCAmelCase__		(UpperCamelCase_							,UpperCamelCase_							,UpperCamelCase_=None       ):
  
  
  
       """simple docstring"""
  
  
  
  
  
  
       if seed is not None:  # useful for obtaining consistent results
            np.random.seed(UpperCamelCase_       )
       snake_case					=       data.shape[0]  # number of data points
  
       # Pick K indices from range [0, N).
       snake_case					=       np.random.randint(0							,UpperCamelCase_							,UpperCamelCase_       )
  
       # Keep centroids as dense format, as many entries will be nonzero due to averaging.
       # As long as at least one document in a cluster contains a word,
       # it will carry a nonzero weight in the TF-IDF vector of the centroid.
       snake_case					=       data[rand_indices, :]
  
       return centroids
  def     UpperCAmelCase__		(UpperCamelCase_							,UpperCamelCase_       ):
  
  
  
       """simple docstring"""
  
  
  
  
  
  
       return pairwise_distances(UpperCamelCase_							,UpperCamelCase_							,metric='''euclidean'''       )
  def     UpperCAmelCase__		(UpperCamelCase_							,UpperCamelCase_       ):
  
  
  
       """simple docstring"""
  
  
  
  
  
  
       snake_case					=       centroid_pairwise_dist(UpperCamelCase_							,UpperCamelCase_       )
  
       # Compute cluster assignments for each data point:
       # Fill in the blank (RHS only)
       snake_case					=       np.argmin(UpperCamelCase_							,axis=1       )
  
       return cluster_assignment
  def     UpperCAmelCase__		(UpperCamelCase_							,UpperCamelCase_							,UpperCamelCase_       ):
  
  
  
       """simple docstring"""
  
  
  
  
  
  
       snake_case					=       []
       for i in range(UpperCamelCase_       ):
            # Select all data points that belong to cluster i. Fill in the blank (RHS only)
            snake_case					=       data[cluster_assignment == i]
            # Compute the mean of the data points. Fill in the blank (RHS only)
            snake_case					=       member_data_points.mean(axis=0       )
            new_centroids.append(UpperCamelCase_       )
       snake_case					=       np.array(UpperCamelCase_       )
  
       return new_centroids
  def     UpperCAmelCase__		(UpperCamelCase_							,UpperCamelCase_							,UpperCamelCase_							,UpperCamelCase_       ):
  
  
  
       """simple docstring"""
  
  
  
  
  
  
       snake_case					=       0.0
       for i in range(UpperCamelCase_       ):
            # Select all data points that belong to cluster i. Fill in the blank (RHS only)
            snake_case					=       data[cluster_assignment == i, :]
  
            if member_data_points.shape[0] > 0:  # check if i-th cluster is non-empty
                 # Compute distances from centroid to data points (RHS only)
                 snake_case					=       pairwise_distances(
                     UpperCamelCase_							,[centroids[i]]							,metric='''euclidean'''       )
                 snake_case					=       distances**2
                 heterogeneity += np.sum(UpperCamelCase_       )
  
       return heterogeneity
  def     UpperCAmelCase__		(UpperCamelCase_							,UpperCamelCase_       ):
  
  
  
       """simple docstring"""
  
  
  
  
  
  
       plt.figure(figsize=(7, 4)       )
       plt.plot(UpperCamelCase_							,linewidth=4       )
       plt.xlabel('''# Iterations'''       )
       plt.ylabel('''Heterogeneity'''       )
       plt.title(F'''Heterogeneity of clustering over time, K={k:d}'''       )
       plt.rcParams.update({'''font.size''': 16}       )
       plt.show()
  def     UpperCAmelCase__		(UpperCamelCase_							,UpperCamelCase_							,UpperCamelCase_							,UpperCamelCase_=5_00							,UpperCamelCase_=None							,UpperCamelCase_=False       ):
  
  
  
       """simple docstring"""
  
  
  
  
  
  
       snake_case					=       initial_centroids[:]
       snake_case					=       None
  
       for itr in range(UpperCamelCase_       ):
            if verbose:
                 print(UpperCamelCase_							,end=''''''       )
  
            # 1. Make cluster assignments using nearest centroids
            snake_case					=       assign_clusters(UpperCamelCase_							,UpperCamelCase_       )
  
            # 2. Compute a new centroid for each of the k clusters, averaging all data
            #    points assigned to that cluster.
            snake_case					=       revise_centroids(UpperCamelCase_							,UpperCamelCase_							,UpperCamelCase_       )
  
            # Check for convergence: if none of the assignments changed, stop
            if (
                prev_cluster_assignment is not None
                and (prev_cluster_assignment == cluster_assignment).all()
            ):
                 break
  
            # Print number of new assignments
            if prev_cluster_assignment is not None:
                 snake_case					=       np.sum(prev_cluster_assignment != cluster_assignment       )
                 if verbose:
                      print(
                          F'''    {num_changed:5d} elements changed their cluster assignment.'''       )
  
          # Record heterogeneity convergence metric
            if record_heterogeneity is not None:
                 # YOUR CODE HERE
                 snake_case					=       compute_heterogeneity(UpperCamelCase_							,UpperCamelCase_							,UpperCamelCase_							,UpperCamelCase_       )
                 record_heterogeneity.append(UpperCamelCase_       )
  
            snake_case					=       cluster_assignment[:]
  
       return centroids, cluster_assignment
  
  
  # Mock test below
  if False:  # change to true to run this test case.
   from sklearn import datasets as ds
  
   _SCREAMING_SNAKE_CASE    :				Optional[Any]       =					ds.load_iris()
   _SCREAMING_SNAKE_CASE    :				Optional[Any]       =					3
   _SCREAMING_SNAKE_CASE    :				int       =					[]
   _SCREAMING_SNAKE_CASE    :				int       =					get_initial_centroids(dataset["data"], k, seed=0)
   _SCREAMING_SNAKE_CASE    :				Any       =					kmeans(
       dataset["data"],
       k,
       initial_centroids,
       maxiter=4_00,
       record_heterogeneity=heterogeneity,
       verbose=True,
   )
   plot_heterogeneity(heterogeneity, k)
  def     UpperCAmelCase__		(UpperCamelCase_							,UpperCamelCase_							,UpperCamelCase_=None       ):
  
  
  
       """simple docstring"""
  
  
  
  
  
  
       if fill_missing_report:
            snake_case					=       df.fillna(value=UpperCamelCase_       )
       snake_case					=       1
       snake_case					=       df.select_dtypes(np.number       ).columns
       snake_case					=       (
           df.groupby(['''Cluster''']       )[  # construct report dataframe
               numeric_cols
           ]  # group by cluster number
           .agg(
               [
                   ('''sum''', np.sum),
                   ('''mean_with_zeros''', lambda UpperCamelCase_       : np.mean(np.nan_to_num(UpperCamelCase_       )       )),
                   ('''mean_without_zeros''', lambda UpperCamelCase_       : x.replace(0							,np.NaN       ).mean()),
                   (
                       '''mean_25-75''',
                       lambda UpperCamelCase_       : np.mean(
                           np.nan_to_num(
                               sorted(UpperCamelCase_       )[
                                   round(len(UpperCamelCase_       ) * 25 / 1_00       ) : round(len(UpperCamelCase_       ) * 75 / 1_00       )
                               ]       )       ),
                   ),
                   ('''mean_with_na''', np.mean),
                   ('''min''', lambda UpperCamelCase_       : x.min()),
                   ('''5%''', lambda UpperCamelCase_       : x.quantile(0.05       )),
                   ('''25%''', lambda UpperCamelCase_       : x.quantile(0.25       )),
                   ('''50%''', lambda UpperCamelCase_       : x.quantile(0.50       )),
                   ('''75%''', lambda UpperCamelCase_       : x.quantile(0.75       )),
                   ('''95%''', lambda UpperCamelCase_       : x.quantile(0.95       )),
                   ('''max''', lambda UpperCamelCase_       : x.max()),
                   ('''count''', lambda UpperCamelCase_       : x.count()),
                   ('''stdev''', lambda UpperCamelCase_       : x.std()),
                   ('''mode''', lambda UpperCamelCase_       : x.mode()[0]),
                   ('''median''', lambda UpperCamelCase_       : x.median()),
                   ('''# > 0''', lambda UpperCamelCase_       : (x > 0).sum()),
               ]       )
           .T.reset_index()
           .rename(index=UpperCamelCase_							,columns={'''level_0''': '''Features''', '''level_1''': '''Type'''}       )
       )  # rename columns
       # calculate the size of cluster(count of clientID's)
       snake_case					=       report[
           (report['''Features'''] == '''dummy''') & (report['''Type'''] == '''count''')
       ].copy()  # avoid SettingWithCopyWarning
       snake_case					=       (
           '''ClusterSize'''  # rename created cluster df to match report column names
       )
       snake_case					=       '''# of Customers'''
       snake_case					=       pd.DataFrame(
           clustersize.iloc[:, 2:].values
           / clustersize.iloc[:, 2:].values.sum()       )
       snake_case					=       '''% of Customers'''  # rename created cluster df to match report column names
       snake_case					=       '''ClusterProportion'''
       snake_case					=       clusterproportion.columns.tolist()
       snake_case					=       cols[-2:] + cols[:-2]
       snake_case					=       clusterproportion[cols]  # rearrange columns to match report
       snake_case					=       report.columns
       snake_case					=       pd.DataFrame(
           abs(
               report[report['''Type'''] == '''count'''].iloc[:, 2:].values
               - clustersize.iloc[:, 2:].values       )       )  # generating df with count of nan values
       snake_case					=       0
       snake_case					=       '''# of nan'''
       snake_case					=       report[
           report['''Type'''] == '''count'''
       ].Features.tolist()  # filling values in order to match report
       snake_case					=       a.columns.tolist()
       snake_case					=       cols[-2:] + cols[:-2]
       snake_case					=       a[cols]  # rearrange columns to match report
       snake_case					=       report.columns  # rename columns to match report
       snake_case					=       report.drop(
           report[report.Type == '''count'''].index       )  # drop count values except cluster size
       snake_case					=       pd.concat(
           [report, a, clustersize, clusterproportion]							,axis=0       )  # concat report with clustert size and nan values
       snake_case					=       report['''Features'''].isin(UpperCamelCase_       )
       snake_case					=       report.columns.tolist()
       snake_case					=       cols[0:2] + cols[-1:] + cols[2:-1]
       snake_case					=       report[cols]
       snake_case					=       {
           '''ClusterSize''': 9,
           '''ClusterProportion''': 8,
           '''mean_with_zeros''': 7,
           '''mean_with_na''': 6,
           '''max''': 5,
           '''50%''': 4,
           '''min''': 3,
           '''25%''': 2,
           '''75%''': 1,
           '''# of nan''': 0,
           '''# > 0''': -1,
           '''sum_with_na''': -2,
       }
       snake_case					=       (
           report.assign(
               Sortera=lambda UpperCamelCase_       : x.Type.map(UpperCamelCase_       )							,Sortera=lambda UpperCamelCase_       : list(reversed(range(len(UpperCamelCase_       )       )       )       )							,)
           .sort_values(['''Sorter1''', '''Mark''', '''Sorter2''']							,ascending=UpperCamelCase_       )
           .drop(['''Sorter1''', '''Sorter2''']							,axis=1       )
       )
       snake_case					=       ''''''
       snake_case					=       report.reset_index()
       snake_case					=       report.drop(columns=['''index''']       )
       return report
  
  
  if __name__ == "__main__":
   import doctest
  
   doctest.testmod()
  
  
  
  
  
style_context: 
  
  
  from typing import TYPE_CHECKING
  
  from ...utils import (
      OptionalDependencyNotAvailable,
      _LazyModule,
      is_tf_available,
      is_tokenizers_available,
      is_torch_available,
  )
  
  
  _SCREAMING_SNAKE_CASE    :				Optional[int]       =					{
      "configuration_layoutlm": ["LAYOUTLM_PRETRAINED_CONFIG_ARCHIVE_MAP", "LayoutLMConfig", "LayoutLMOnnxConfig"],
      "tokenization_layoutlm": ["LayoutLMTokenizer"],
  }
  
  try:
   if not is_tokenizers_available():
    raise OptionalDependencyNotAvailable()
  except OptionalDependencyNotAvailable:
   pass
  else:
   _SCREAMING_SNAKE_CASE    :				str       =					["LayoutLMTokenizerFast"]
  
  try:
   if not is_torch_available():
    raise OptionalDependencyNotAvailable()
  except OptionalDependencyNotAvailable:
   pass
  else:
   _SCREAMING_SNAKE_CASE    :				List[str]       =					[
       "LAYOUTLM_PRETRAINED_MODEL_ARCHIVE_LIST",
       "LayoutLMForMaskedLM",
       "LayoutLMForSequenceClassification",
       "LayoutLMForTokenClassification",
       "LayoutLMForQuestionAnswering",
       "LayoutLMModel",
       "LayoutLMPreTrainedModel",
   ]
  
  try:
   if not is_tf_available():
    raise OptionalDependencyNotAvailable()
  except OptionalDependencyNotAvailable:
   pass
  else:
   _SCREAMING_SNAKE_CASE    :				Optional[int]       =					[
       "TF_LAYOUTLM_PRETRAINED_MODEL_ARCHIVE_LIST",
       "TFLayoutLMForMaskedLM",
       "TFLayoutLMForSequenceClassification",
       "TFLayoutLMForTokenClassification",
       "TFLayoutLMForQuestionAnswering",
       "TFLayoutLMMainLayer",
       "TFLayoutLMModel",
       "TFLayoutLMPreTrainedModel",
   ]
  
  
  if TYPE_CHECKING:
   from .configuration_layoutlm import LAYOUTLM_PRETRAINED_CONFIG_ARCHIVE_MAP, LayoutLMConfig, LayoutLMOnnxConfig
   from .tokenization_layoutlm import LayoutLMTokenizer
  
   try:
    if not is_tokenizers_available():
     raise OptionalDependencyNotAvailable()
   except OptionalDependencyNotAvailable:
    pass
   else:
    from .tokenization_layoutlm_fast import LayoutLMTokenizerFast
  
   try:
    if not is_torch_available():
     raise OptionalDependencyNotAvailable()
   except OptionalDependencyNotAvailable:
    pass
   else:
    from .modeling_layoutlm import (
        LAYOUTLM_PRETRAINED_MODEL_ARCHIVE_LIST,
        LayoutLMForMaskedLM,
        LayoutLMForQuestionAnswering,
        LayoutLMForSequenceClassification,
        LayoutLMForTokenClassification,
        LayoutLMModel,
        LayoutLMPreTrainedModel,
    )
   try:
    if not is_tf_available():
     raise OptionalDependencyNotAvailable()
   except OptionalDependencyNotAvailable:
    pass
   else:
    from .modeling_tf_layoutlm import (
        TF_LAYOUTLM_PRETRAINED_MODEL_ARCHIVE_LIST,
        TFLayoutLMForMaskedLM,
        TFLayoutLMForQuestionAnswering,
        TFLayoutLMForSequenceClassification,
        TFLayoutLMForTokenClassification,
        TFLayoutLMMainLayer,
        TFLayoutLMModel,
        TFLayoutLMPreTrainedModel,
    )
  
  else:
   import sys
  
   _SCREAMING_SNAKE_CASE    :				Optional[int]       =					_LazyModule(__name__, globals()["__file__"], _import_structure, module_spec=__spec__)
  
  
  
  
  