(request, context)
Look for clusters within a dimension using the given features. Scalar function.
        Three variants are implemented:
        :0: one dimension and a string of numeric features.
        :1: two dimensions and one measure. This will only work when used in the Qlik load script.
        :2: one dimension, the latitude and longitude.
        :
        :param request: an iterable sequence of RowData
        :param context:
        :return: the clustering classification for each row
        :Qlik expression examples:
        :<AAI Connection Name>.Cluster(dimension, sum(value1) & ';' & sum(value2), 'scaler=standard')
Look for clusters within a dimension using the given features. Scalar function.
        Three variants are implemented:
        :0: one dimension and a string of numeric features.
        :1: two dimensions and one measure. This will only work when used in the Qlik load script.
        :2: one dimension, the latitude and longitude.
        :
        :param request: an iterable sequence of RowData
        :param context:
        :return: the clustering classification for each row
        :Qlik expression examples:
        :<AAI Connection Name>.Cluster(dimension, sum(value1) & ';' & sum(value2), 'scaler=standard')
Look for clusters within a dimension using the given features . Scalar function . Three variants are implemented : : 0 : one dimension and a string of numeric features . : 1 : two dimensions and one measure . This will only work when used in the Qlik load script . : 2 : one dimension the latitude and longitude . : : param request : an iterable sequence of RowData : param context : : return : the clustering classification for each row : Qlik expression examples : : <AAI Connection Name > . Cluster ( dimension sum ( value1 ) & ; & sum ( value2 ) scaler = standard )
def _cluster(request, context):
        """
        Look for clusters within a dimension using the given features. Scalar function.
        Three variants are implemented:
        :0: one dimension and a string of numeric features.
        :1: two dimensions and one measure. This will only work when used in the Qlik load script.
        :2: one dimension, the latitude and longitude.
        :
        :param request: an iterable sequence of RowData
        :param context:
        :return: the clustering classification for each row
        :Qlik expression examples:
        :<AAI Connection Name>.Cluster(dimension, sum(value1) & ';' & sum(value2), 'scaler=standard')
        """
        # Get a list from the generator object so that it can be iterated over multiple times
        request_list = [request_rows for request_rows in request]
        
        # Get the function id from the header to determine the variant being called
        function = ExtensionService._get_function_id(context)
               
        if function == 0:
            # The standard variant takes in one dimension and a string of semi-colon separated features.
            variant = "standard"
        elif function == 1:
            # In the second variant features for clustering are produced by pivoting the measure for the second dimension.
            variant = "two_dims"
        elif function == 2:
            # The third variant if for finding clusters in geospatial coordinates.
            variant = "lat_long"
        
        # Create an instance of the HDBSCANForQlik class
        # This will take the request data from Qlik and prepare it for clustering
        clusterer = HDBSCANForQlik(request_list, context, variant=variant)
        
        # Calculate the clusters and store in a Pandas series (or DataFrame in the case of a load script call)
        clusters = clusterer.scan()
        
        # Check if the response is a DataFrame. 
        # This occurs when the load_script=true argument is passed in the Qlik expression.
        response_is_df = isinstance(clusters, pd.DataFrame)
        
        # Convert the response to a list of rows
        clusters = clusters.values.tolist()
        
        # We convert values to type SSE.Dual, and group columns into a iterable
        if response_is_df:
            response_rows = [iter([SSE.Dual(strData=row[0]),SSE.Dual(numData=row[1])]) for row in clusters]
        else:
            response_rows = [iter([SSE.Dual(numData=row)]) for row in clusters]
        
        # Values are then structured as SSE.Rows
        response_rows = [SSE.Row(duals=duals) for duals in response_rows]

        # Get the number of bundles in the request
        num_request_bundles = len(request_list)

        # Get the number of rows in the response
        num_rows = len(response_rows) 

        # Calculate the number of rows to send per bundle
        if num_rows >= num_request_bundles:
            rows_per_bundle = num_rows//num_request_bundles
        else:
            rows_per_bundle = num_rows

        # Stream response as BundledRows
        for i in range(0, num_rows, rows_per_bundle):
            # Yield Row data as Bundled rows
            yield SSE.BundledRows(rows=response_rows[i : i + rows_per_bundle])
def _cluster ( request , context ) : # Get a list from the generator object so that it can be iterated over multiple times request_list = [ request_rows for request_rows in request ] # Get the function id from the header to determine the variant being called function = ExtensionService . _get_function_id ( context ) if function == 0 : # The standard variant takes in one dimension and a string of semi-colon separated features. variant = "standard" elif function == 1 : # In the second variant features for clustering are produced by pivoting the measure for the second dimension. variant = "two_dims" elif function == 2 : # The third variant if for finding clusters in geospatial coordinates. variant = "lat_long" # Create an instance of the HDBSCANForQlik class # This will take the request data from Qlik and prepare it for clustering clusterer = HDBSCANForQlik ( request_list , context , variant = variant ) # Calculate the clusters and store in a Pandas series (or DataFrame in the case of a load script call) clusters = clusterer . scan ( ) # Check if the response is a DataFrame.  # This occurs when the load_script=true argument is passed in the Qlik expression. response_is_df = isinstance ( clusters , pd . DataFrame ) # Convert the response to a list of rows clusters = clusters . values . tolist ( ) # We convert values to type SSE.Dual, and group columns into a iterable if response_is_df : response_rows = [ iter ( [ SSE . Dual ( strData = row [ 0 ] ) , SSE . Dual ( numData = row [ 1 ] ) ] ) for row in clusters ] else : response_rows = [ iter ( [ SSE . Dual ( numData = row ) ] ) for row in clusters ] # Values are then structured as SSE.Rows response_rows = [ SSE . Row ( duals = duals ) for duals in response_rows ] # Get the number of bundles in the request num_request_bundles = len ( request_list ) # Get the number of rows in the response num_rows = len ( response_rows ) # Calculate the number of rows to send per bundle if num_rows >= num_request_bundles : rows_per_bundle = num_rows // num_request_bundles else : rows_per_bundle = num_rows # Stream response as BundledRows for i in range ( 0 , num_rows , rows_per_bundle ) : # Yield Row data as Bundled rows yield SSE . BundledRows ( rows = response_rows [ i : i + rows_per_bundle ] )