Python 3.x 伟大的期望定制期望不按要求忽略空值

Python 3.x 伟大的期望定制期望不按要求忽略空值,python-3.x,pandas,dataframe,great-expectations,Python 3.x,Pandas,Dataframe,Great Expectations,我们正在使用的库的版本: 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中获取数据,然后将其数据帧输入到《远大前程》中。我知道GE有一个雪花数据源,它在我的列表中。但我认为即使不使用该数据源,这种设置也应该有效 我们对数据上下文

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

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中获取数据,然后将其数据帧输入到《远大前程》中。我知道GE有一个雪花数据源,它在我的列表中。但我认为即使不使用该数据源,这种设置也应该有效

我们对数据上下文配置抱有以下期望:

    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
稍后,我们将验证数据上下文,如下所示:

    return ge_context.run_validation_operator(
        "action_list_operator",
        assets_to_validate=batches,
        run_id=run_id)["success"]
在我们的数据中,
a
b
列通常为
null
。鉴于我已在自定义期望上设置了
ignore\u row\u if='any\u value\u missing'
标志,我希望跳过
a
b
c
列中的
null
值的行。但是《远大前程》并没有跳过它们,而是将它们添加到输出的“意外”或“失败”字段中:

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
我不确定为什么会这样。在《远大前程》中,
multi-column\u map\u expection
实现了:

...
            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
(不将它们添加到
意外的
列表中,也不使用它们来确定
成功率
)。我在我们的代码中删除了一个
pdb
,并验证了我们调用期望值的数据帧可以以正确的方式进行操作,以获得“合理”的数据(
test_df.isnull().any(axis=1)
),但出于某种原因,巨大的期望值允许这些空值通过。有人知道为什么吗?

我相信海报在这里提出了一个Github问题:。可以在那里跟踪进度

...
            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
            )