Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cdisc_rules_engine/models/operation_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class OperationParams:
returntype: str = None
source: str = None
target: str = None
subtract: str = None
value_is_reference: bool = False
namespace: str = None
delimiter: str = None
46 changes: 46 additions & 0 deletions cdisc_rules_engine/operations/minus.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
"""
Set difference operation: name minus subtract.
Returns elements in name that are not in subtract, preserving order from name.
"""

from cdisc_rules_engine.operations.base_operation import BaseOperation


def _normalize_to_list(val):
"""Convert value to a list for set operations."""
if val is None:
return []
if isinstance(val, list):
return val
if isinstance(val, (set, tuple)):
return list(val)
return [val]


def _set_difference_preserve_order(list_a: list, list_b: list) -> list:
"""
Compute set difference A \\ B (elements in A not in B).
Preserves order from list_a.
"""
set_b = set(_normalize_to_list(list_b))
return [x for x in _normalize_to_list(list_a) if x not in set_b]


class Minus(BaseOperation):
"""
Operation that computes set difference: name minus subtract.
name (minuend) and subtract (subtrahend) reference other operation results.
Returns elements in name that are not in subtract.
"""

def _execute_operation(self):
name_ref = self.params.target
subtract_ref = self.params.subtract

if not name_ref or name_ref not in self.evaluation_dataset.columns:
return []
list_a = self.evaluation_dataset[name_ref].iloc[0]
if not subtract_ref or subtract_ref not in self.evaluation_dataset.columns:
return _normalize_to_list(list_a)
list_b = self.evaluation_dataset[subtract_ref].iloc[0]
return _set_difference_preserve_order(list_a, list_b)
2 changes: 2 additions & 0 deletions cdisc_rules_engine/operations/operations_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
MedDRATermReferencesValidator,
)
from cdisc_rules_engine.operations.min_date import MinDate
from cdisc_rules_engine.operations.minus import Minus
from cdisc_rules_engine.operations.minimum import Minimum
from cdisc_rules_engine.operations.record_count import RecordCount
from cdisc_rules_engine.operations.split_by import SplitBy
Expand Down Expand Up @@ -109,6 +110,7 @@ class OperationsFactory(FactoryInterface):
"mean": Mean,
"min": Minimum,
"min_date": MinDate,
"minus": Minus,
"record_count": RecordCount,
"valid_meddra_code_references": MedDRACodeReferencesValidator,
"valid_whodrug_references": WhodrugReferencesValidator,
Expand Down
1 change: 1 addition & 0 deletions cdisc_rules_engine/utilities/rule_processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ def perform_rule_operations(
operation_id=operation.get("id"),
operation_name=operation.get("operator"),
original_target=original_target,
subtract=operation.get("subtract"),
regex=operation.get("regex"),
returntype=operation.get("returntype"),
source=operation.get("source"),
Expand Down
117 changes: 90 additions & 27 deletions resources/schema/rule/Operations.json
Original file line number Diff line number Diff line change
Expand Up @@ -50,42 +50,54 @@
},
{
"properties": {
"operator": { "const": "domain_is_custom" }
"operator": {
"const": "domain_is_custom"
}
},
"required": ["id", "operator"],
"type": "object"
},
{
"properties": {
"operator": { "const": "domain_label" }
"operator": {
"const": "domain_label"
}
},
"required": ["id", "operator"],
"type": "object"
},
{
"properties": {
"operator": { "const": "dy" }
"operator": {
"const": "dy"
}
},
"required": ["id", "operator", "name"],
"type": "object"
},
{
"properties": {
"operator": { "const": "extract_metadata" }
"operator": {
"const": "extract_metadata"
}
},
"required": ["id", "operator", "name"],
"type": "object"
},
{
"properties": {
"operator": { "const": "expected_variables" }
"operator": {
"const": "expected_variables"
}
},
"required": ["id", "operator"],
"type": "object"
},
{
"properties": {
"operator": { "const": "get_codelist_attributes" }
"operator": {
"const": "get_codelist_attributes"
}
},
"required": ["id", "operator", "name", "ct_attribute", "version"],
"type": "object"
Expand Down Expand Up @@ -162,46 +174,67 @@
},
{
"properties": {
"operator": { "const": "map" }
"operator": {
"const": "map"
}
},
"required": ["id", "operator", "map"],
"type": "object"
},
{
"properties": {
"operator": { "const": "max" }
"operator": {
"const": "max"
}
},
"required": ["id", "operator", "name"],
"type": "object"
},
{
"properties": {
"operator": { "const": "max_date" }
"operator": {
"const": "max_date"
}
},
"required": ["id", "operator", "name"],
"type": "object"
},
{
"properties": {
"operator": { "const": "mean" }
"operator": {
"const": "mean"
}
},
"required": ["id", "operator", "name"],
"type": "object"
},
{
"properties": {
"operator": { "const": "min" }
"operator": {
"const": "min"
}
},
"required": ["id", "operator", "name"],
"type": "object"
},
{
"properties": {
"operator": { "const": "min_date" }
"operator": {
"const": "min_date"
}
},
"required": ["id", "operator", "name"],
"type": "object"
},
{
"properties": {
"operator": {
"const": "minus"
}
},
"required": ["id", "operator", "name", "subtract"],
"type": "object"
},
{
"properties": {
"operator": {
Expand All @@ -222,42 +255,54 @@
},
{
"properties": {
"operator": { "const": "record_count" }
"operator": {
"const": "record_count"
}
},
"required": ["id", "operator"],
"type": "object"
},
{
"properties": {
"operator": { "const": "required_variables" }
"operator": {
"const": "required_variables"
}
},
"required": ["id", "operator"],
"type": "object"
},
{
"properties": {
"operator": { "const": "split_by" }
"operator": {
"const": "split_by"
}
},
"required": ["id", "operator", "delimiter", "name"],
"type": "object"
},
{
"properties": {
"operator": { "const": "study_domains" }
"operator": {
"const": "study_domains"
}
},
"required": ["id", "operator"],
"type": "object"
},
{
"properties": {
"operator": { "const": "dataset_names" }
"operator": {
"const": "dataset_names"
}
},
"required": ["id", "operator"],
"type": "object"
},
{
"properties": {
"operator": { "const": "standard_domains" }
"operator": {
"const": "standard_domains"
}
},
"required": ["id", "operator"],
"type": "object"
Expand All @@ -280,7 +325,6 @@
"required": ["id", "operator", "external_dictionary_type"],
"type": "object"
},

{
"properties": {
"operator": {
Expand Down Expand Up @@ -364,28 +408,36 @@
},
{
"properties": {
"operator": { "const": "variable_count" }
"operator": {
"const": "variable_count"
}
},
"required": ["id", "operator"],
"type": "object"
},
{
"properties": {
"operator": { "const": "variable_exists" }
"operator": {
"const": "variable_exists"
}
},
"required": ["id", "operator"],
"type": "object"
},
{
"properties": {
"operator": { "const": "variable_is_null" }
"operator": {
"const": "variable_is_null"
}
},
"required": ["id", "operator"],
"type": "object"
},
{
"properties": {
"operator": { "const": "variable_names" }
"operator": {
"const": "variable_names"
}
},
"required": ["id", "operator"],
"type": "object"
Expand All @@ -410,7 +462,9 @@
},
{
"properties": {
"operator": { "const": "get_xhtml_errors" }
"operator": {
"const": "get_xhtml_errors"
}
},
"required": ["id", "operator", "name", "namespace"],
"type": "object"
Expand Down Expand Up @@ -457,7 +511,9 @@
]
},
"ct_package_types": {
"items": { "$ref": "Operations.json#/properties/ct_package_type" },
"items": {
"$ref": "Operations.json#/properties/ct_package_type"
},
"type": "array"
},
"ct_packages": {
Expand Down Expand Up @@ -488,7 +544,9 @@
"external_dictionary_type": {
"enum": ["meddra"]
},
"filter": { "type": "object" },
"filter": {
"type": "object"
},
"filter_key": {
"type": "string"
},
Expand Down Expand Up @@ -536,7 +594,9 @@
"items": {
"type": "object",
"properties": {
"output": { "type": "string" }
"output": {
"type": "string"
}
},
"required": ["output"]
}
Expand All @@ -560,6 +620,9 @@
"source": {
"type": "string"
},
"subtract": {
"type": "string"
},
"term_value": {
"type": "string"
},
Expand Down
Loading
Loading