code: def crowd_distance(self,obs_df):
          
  
          # initialize the distance container
          crowd_distance = pd.Series(data=0.0,index=obs_df.index)
  
          for name,direction in self.obs_dict.items():
              # make a copy - wasteful, but easier
              obj_df = obs_df.loc[:,name].copy()
  
              # sort so that largest values are first
              obj_df.sort_values(ascending=False,inplace=True)
  
              # set the ends so they are always retained
              crowd_distance.loc[obj_df.index[0]] += self.max_distance
              crowd_distance.loc[obj_df.index[-1]] += self.max_distance
  
              # process the vector
              i = 1
              for idx in obj_df.index[1:-1]:
                  crowd_distance.loc[idx] += obj_df.iloc[i-1] - obj_df.iloc[i+1]
                  i += 1
  
          return crowd_distance
docs: determine the crowding distance for each candidate solution
  
          Parameters
          ----------
          obs_df : pandas.DataFrame
              dataframe with columns of observation names and rows of realizations
  
          Returns
          -------
          crowd_distance : pandas.Series
              series with index of obs_df and values of crowd distance