def add_column_to_workflow( user, workflow: models.Workflow, column: models.Column, column_initial_value: Any, action_column_event: Optional[str] = None, action: Optional[models.Action] = None, ): """Add a new column to the workflow. :param user: User executing the operation :param workflow: Used workflow :param column: Column to insert :param column_initial_value: Initial value for the column :param action_column_event: Event to record if the action/column needs to be stored :param action: If the column is a question, this is the action in which it is being used. :return: Nothing. Column added to Wflow and DB """ # Catch the special case of integer type and no initial value. Pandas # encodes it as NaN but a cycle through the database transforms it into # a string. To avoid this case, integer + empty value => double if column.data_type == 'integer' and column_initial_value is None: column.data_type = 'double' # Fill in the remaining fields in the column column.workflow = workflow column.is_key = False # Update the positions of the appropriate columns workflow.reposition_columns(workflow.ncols + 1, column.position) # Save column, refresh workflow, and increase number of columns column.save() workflow.refresh_from_db() workflow.ncols += 1 workflow.set_query_builder_ops() workflow.save() # Add the new column to the DB try: sql.add_column_to_db( workflow.get_data_frame_table_name(), column.name, column.data_type, initial=column_initial_value) except Exception as exc: raise services.OnTaskWorkflowAddColumn( message=_('Unable to add element: {0}').format(str(exc)), to_delete=[column]) if action_column_event: acc, __ = models.ActionColumnConditionTuple.objects.get_or_create( action=action, column=column, condition=None) acc.log(user, action_column_event) column.log(user, models.Log.COLUMN_ADD)
def add_formula_column( user, workflow: models.Workflow, column: models.Column, operation: str, selected_columns: List[models.Column], ): """Add the formula column to the workflow. :param user: User making the request :param workflow: Workflow to add the column :param column: Column being added :param operation: string denoting the operation :param selected_columns: List of columns selected for the operation. :return: Column is added to the workflow """ # Save the column object attached to the form and add additional fields column.workflow = workflow column.is_key = False # Save the instance column.save() # Update the data frame df = pandas.load_table(workflow.get_data_frame_table_name()) # Add the column with the appropriate computation cnames = [col.name for col in selected_columns] df[column.name] = _op_distrib[operation](df[cnames]) # Populate the column type column.data_type = pandas.datatype_names.get( df[column.name].dtype.name) # Update the positions of the appropriate columns workflow.reposition_columns(workflow.ncols + 1, column.position) column.save() workflow.refresh_from_db() # Store the df to DB try: pandas.store_dataframe(df, workflow) except Exception as exc: raise services.OnTaskWorkflowAddColumn( message=_('Unable to add column: {0}').format(str(exc)), to_delete=[column]) workflow.ncols = workflow.columns.count() workflow.save() column.log(user, models.Log.COLUMN_ADD_FORMULA)
def add_random_column( user, workflow: models.Workflow, column: models.Column, data_frame: pd.DataFrame, ): """Add the formula column to the workflow. :param user: User making the request :param workflow: Workflow to add the column :param column: Column being added :param data_frame: Data frame of the current workflow :return: Column is added to the workflow """ # Save the column object attached to the form and add additional fields column.workflow = workflow column.is_key = False # Detect the case of a single integer as initial value so that it is # expanded try: int_value = int(column.categories[0]) if int_value <= 1: raise services.OnTaskWorkflowIntegerLowerThanOne( field_name='values', message=_('The integer value has to be larger than 1')) column.set_categories([idx + 1 for idx in range(int_value)]) except (ValueError, TypeError, IndexError): pass column.save() # Empty new column new_column = [None] * workflow.nrows # Create the random partitions partitions = _partition([idx for idx in range(workflow.nrows)], len(column.categories)) # Assign values to partitions for idx, indexes in enumerate(partitions): for col_idx in indexes: new_column[col_idx] = column.categories[idx] # Assign the new column to the data frame data_frame[column.name] = new_column # Update the positions of the appropriate columns workflow.reposition_columns(workflow.ncols + 1, column.position) workflow.refresh_from_db() # Store the df to DB try: pandas.store_dataframe(data_frame, workflow) except Exception as exc: raise services.OnTaskWorkflowStoreError( message=_('Unable to add the column: {0}').format(str(exc)), to_delete=[column]) workflow.ncols = workflow.columns.count() workflow.save() # Log the event column.log(user, models.Log.COLUMN_ADD_RANDOM)