0

我们正在使用的库的版本:

snowconn==3.7.1
snowflake-connector-python==2.3.10
snowflake-sqlalchemy==1.2.3
SQLAlchemy==1.3.23
great_expectations==0.13.10
pandas==1.1.5

请注意,我们自己从 Snowflake 中获取数据,然后将其数据框输入到 Great Expectations 中。我知道 GE 有一个 Snowflake 数据源,它在我的列表中以添加它。但我认为即使不使用该数据源,此设置也应该有效。

我们有以下 Great Expectations 数据上下文配置:

    data_context_config = DataContextConfig(
        datasources={
            datasource_name: DatasourceConfig(
                class_name='PandasDatasource',
                data_asset_type={
                    'module_name': 'dataqa.dataset',
                    'class_name': 'CustomPandasDataset'
                }
            )
        },
        store_backend_defaults=S3StoreBackendDefaults(
            default_bucket_name=METADATA_BUCKET,
            expectations_store_prefix=EXPECTATIONS_PATH,
            validations_store_prefix=VALIDATIONS_PATH,
            data_docs_prefix=DATA_DOCS_PATH,
        ),
        validation_operators={
            "action_list_operator": {
                "class_name": "ActionListValidationOperator",
                "action_list": [
                    {
                        "name": "store_validation_result",
                        "action": {"class_name": "StoreValidationResultAction"},
                    },
                    {
                        "name": "store_evaluation_params",
                        "action": {"class_name": "StoreEvaluationParametersAction"},
                    },
                    {
                        "name": "update_data_docs",
                        "action": {"class_name": "UpdateDataDocsAction"},
                    },
                ],
            }
        }
    )
    ge_context = BaseDataContext(project_config=data_context_config)

CustomPandasDataset定义为:

class CustomPandasDataset(PandasDataset):
    _data_asset_type = "CustomPandasDataset"

    @MetaPandasDataset.multicolumn_map_expectation
    def expect_column_A_equals_column_B_column_C_ratio(
        self,
        column_list,
        ignore_row_if='any_value_is_missing'
    ):
        column_a = column_list.iloc[:,0]
        column_b = column_list.iloc[:,1]
        column_c = column_list.iloc[:,2]

        return abs(column_a - (1.0 - (column_b/column_c))) <= 0.001

并称为:

    cols = ['a', 'b', 'c']
    batch.expect_column_A_equals_column_B_column_C_ratio(
        cols,
        catch_exceptions=True
    )

稍后我们像这样验证数据上下文:

    return ge_context.run_validation_operator(
        "action_list_operator",
        assets_to_validate=batches,
        run_id=run_id)["success"]

很多时候,列abnull我们的数据中。鉴于我已经ignore_row_if='any_value_is_missing'在自定义期望上设置了标志,我期望null在任何列中具有值的行abc被跳过。但是 Great Expectations 并没有跳过它们,而是将它们添加到unexpected输出的 ,或“失败”字段中:

result  
element_count   1000
missing_count   0
missing_percent 0
unexpected_count    849
unexpected_percent  84.89999999999999
unexpected_percent_total    84.89999999999999
unexpected_percent_nonmissing   84.89999999999999result 
element_count   1000
missing_count   0
missing_percent 0
unexpected_count    849
unexpected_percent  84.89999999999999
unexpected_percent_total    84.89999999999999
unexpected_percent_nonmissing   84.89999999999999


partial_unexpected_list 

0   
a   null
b   null
c   1.63

我不确定为什么会这样。在 Great Expectations源代码中,执行以下multicolumn_map_expectation操作:

...
            elif ignore_row_if == "any_value_is_missing":
                boolean_mapped_skip_values = test_df.isnull().any(axis=1)
...
            boolean_mapped_success_values = func(
                self, test_df[boolean_mapped_skip_values == False], *args, **kwargs
            )
            success_count = boolean_mapped_success_values.sum()
            nonnull_count = (~boolean_mapped_skip_values).sum()
            element_count = len(test_df)

            unexpected_list = test_df[
                (boolean_mapped_skip_values == False)
                & (boolean_mapped_success_values == False)
            ]
            unexpected_index_list = list(unexpected_list.index)

            success, percent_success = self._calc_map_expectation_success(
                success_count, nonnull_count, mostly
            )

我将其解释为忽略包含null行(将它们添加到unexpected列表中并且不使用它们来确定percent_success)。我pdb在我们的代码中删除了 a 并验证了我们调用期望的数据帧可以以正确的方式进行操作以获得“合理的”数据 ( test_df.isnull().any(axis=1)),但由于某种原因,Great Expectations 允许这些空值通过。有谁知道为什么?

4

1 回答 1

1

我相信张贴者在这里提交了一个 Github 问题:https ://github.com/great-expectations/great_expectations/issues/2460 。可以在那里跟踪进度。

于 2021-02-25T15:24:59.427 回答