Constrainer API

Constrainer API

合成資料約束處理模組。

類別架構

classDiagram
    class Constrainer {
        dict config
        dict _constrainers
        int resample_trails
        __init__(config)
        apply(df, target_rows) DataFrame
        resample_until_satisfy() DataFrame
        register(name, constraint_class)
    }

    class BaseConstrainer {
        <<abstract>>
        validate_config(df) bool
        apply(df) DataFrame
        _check_columns_exist(df, columns) bool
    }

    class NaNGroupConstrainer {
        dict constraints
        __init__(constraints)
        validate_config(df) None
        apply(df) DataFrame
    }

    class FieldConstrainer {
        list config
        list COMPARISON_OPS
        __init__(config)
        validate_config(df) bool
        apply(df) DataFrame
        _tokenize(condition) list
        _parse_expression() Series
    }

    class FieldCombinationConstrainer {
        list constraints
        __init__(constraints)
        validate_config(df) None
        apply(df) DataFrame
        _validate_constraint_format()
        _is_na_value(value) bool
    }

    class FieldProportionsConstrainer {
        FieldProportionsConfig config
        int _target_rows
        __init__(config)
        validate_config() bool
        apply(df, target_rows) DataFrame
        _constraint_filter_field_proportions()
    }

    class FieldProportionsConfig {
        list fields
        str mode
        float tolerance
        int _target_rows
        verify_data(data, target_n_rows)
        check_proportions(filtered_data)
    }

    BaseConstrainer <|-- NaNGroupConstrainer
    BaseConstrainer <|-- FieldConstrainer
    BaseConstrainer <|-- FieldCombinationConstrainer
    BaseConstrainer <|-- FieldProportionsConstrainer

    Constrainer ..> NaNGroupConstrainer
    Constrainer ..> FieldConstrainer
    Constrainer ..> FieldCombinationConstrainer
    Constrainer ..> FieldProportionsConstrainer
    
    FieldProportionsConstrainer *-- FieldProportionsConfig

    %% 樣式標示
    style Constrainer fill:#e6f3ff,stroke:#4a90e2,stroke-width:3px
    style BaseConstrainer fill:#f3e6ff,stroke:#9966cc,stroke-width:2px
    style NaNGroupConstrainer fill:#fff2e6,stroke:#ff9800,stroke-width:2px
    style FieldConstrainer fill:#fff2e6,stroke:#ff9800,stroke-width:2px
    style FieldCombinationConstrainer fill:#fff2e6,stroke:#ff9800,stroke-width:2px
    style FieldProportionsConstrainer fill:#fff2e6,stroke:#ff9800,stroke-width:2px
    style FieldProportionsConfig fill:#f3e6ff,stroke:#9966cc,stroke-width:2px

基本使用

from petsard import Constrainer

# 從 YAML 配置初始化
constrainer = Constrainer(config)

# 套用約束
constrained_data = constrainer.apply(synthetic_data)

# 驗證資料
validation_result = constrainer.validate(data)

建構函式

def __init__(config: dict)

參數

  • config: 約束配置字典(通常從 YAML 載入)

範例

config = {
    'nan_groups': {...},
    'field_constraints': [...],
    'field_combinations': [...],
    'field_proportions': [...]
}
constrainer = Constrainer(config)

apply()

套用所有約束條件到資料。

def apply(df: pd.DataFrame, target_rows: int = None) -> pd.DataFrame

參數

  • df: 輸入資料框
  • target_rows: 目標列數(可選,供內部使用)

返回

  • 符合所有約束的資料框

範例

result = constrainer.apply(synthetic_data)

validate()

驗證資料是否符合約束,不修改資料。

def validate(
    data: pd.DataFrame,
    return_details: bool = True,
    max_examples_per_rule: int = 6
) -> dict

參數

  • data: 要驗證的資料框
  • return_details: 是否返回詳細違規記錄
  • max_examples_per_rule: 每條規則的違規範例數上限

返回

  • 驗證結果字典,包含:
    • total_rows: 總列數
    • passed_rows: 通過列數
    • failed_rows: 失敗列數
    • pass_rate: 通過率
    • is_fully_compliant: 是否完全符合
    • constraint_violations: 違規統計
    • violation_details: 違規資料(可選)

範例

result = constrainer.validate(data)
print(f"通過率: {result['pass_rate']:.2%}")

if not result['is_fully_compliant']:
    print(result['violation_details'])

resample_until_satisfy()

重複採樣直到滿足約束且達到目標列數。

def resample_until_satisfy(
    data: pd.DataFrame,
    target_rows: int,
    synthesizer,
    postprocessor=None,
    max_trials: int = 300,
    sampling_ratio: float = 10.0,
    verbose_step: int = 10
) -> pd.DataFrame

參數

  • data: 初始資料
  • target_rows: 目標列數
  • synthesizer: 合成器實例
  • postprocessor: 後處理器(可選)
  • max_trials: 最大嘗試次數
  • sampling_ratio: 每次採樣倍數
  • verbose_step: 進度顯示間隔

返回

  • 符合約束且達到目標列數的資料框

範例

result = constrainer.resample_until_satisfy(
    data=pd.DataFrame(),
    target_rows=1000,
    synthesizer=synthesizer,
    max_trials=50
)
print(f"嘗試次數: {constrainer.resample_trails}")

register()

註冊自訂約束類型。

@classmethod
def register(cls, name: str, constraint_class: type)

參數

  • name: 約束類型名稱
  • constraint_class: 繼承自 BaseConstrainer 的類別

範例

class CustomConstrainer(BaseConstrainer):
    def apply(self, df):
        # 自訂邏輯
        return df

Constrainer.register('custom', CustomConstrainer)

方法比較

方法用途修改資料
apply()套用約束並過濾
validate()驗證資料品質
resample_until_satisfy()生成符合約束的資料

注意事項

  • 約束配置建議使用 YAML 檔案定義
  • 約束條件採用嚴格 AND 邏輯組合
  • validate() 不會修改資料,僅用於檢查
  • resample_until_satisfy() 適用於約束嚴格的情況