Great Expectations expect column to contain only integers 当只有一个是坏的时,所有行都失败

Great Expectations expect column to contain only integers fails for all rows when only one is bad

我想使用 great expectations 包来验证 .csv 文件中的列是否仅包含整数。

我正在使用的文件在年龄列中只有整数,除了一行有一个 '`' 字符。这就是我希望捕捉到的。我还在文本编辑器中检查了 .csv 文件,可以确认年龄列中的年龄没有用引号引起来。

然而,期望失败了 100% 的数据。我认为这是因为 pandas 由于一个不正确的行而将列读取为对象类型(因此是一个字符串)。我可以使用 .astype(int) 之类的方法对其进行预处理,因为它会在该行上失败。将 .astype(int) 包装在 try 块中将完全违背对此使用高期望的目的。

这是一个最小的工作示例:

good.csv:

age,name
34,Fred
22,Bob
54,Mary

bad.csv:

age,name
34,Fred
`,Bob
54,Mary

代码:

import great_expectations as ge

df = ge.read_csv("./good.csv");
my_df.expect_column_values_to_be_of_type('age','int')

df = ge.read_csv("./bad.csv");
my_df.expect_column_values_to_be_of_type('age','int')

第一种情况returns

{'success': True,
 'result': {'element_count': 3,
  'missing_count': 0,
  'missing_percent': 0.0,
  'unexpected_count': 0,
  'unexpected_percent': 0.0,
  'unexpected_percent_nonmissing': 0.0,
  'partial_unexpected_list': []}}

所以所有的年龄都是整数并且它在每一行都成功。我预计第二种情况会失败,但只会出现在第二行。但是它在所有行上都失败了:

{'success': False,
 'result': {'element_count': 3,
  'missing_count': 0,
  'missing_percent': 0.0,
  'unexpected_count': 3,
  'unexpected_percent': 1.0,
  'unexpected_percent_nonmissing': 1.0,
  'partial_unexpected_list': ['34', '`', '54']}}

所以我想我期待这样的事情:

{'success': False,
 'result': {'element_count': 3,
  'missing_count': 0,
  'missing_percent': 0.0,
  'unexpected_count': 1,
  'unexpected_percent': 0.33,
  'unexpected_percent_nonmissing': 1.0,
  'partial_unexpected_list': ['`']}}

是我哪里做错了,还是这个包无法做到这一点?

我不知道 great_expectations,但是你可以在 pandas 中简单地使用这个解决这个问题,

print df[pd.to_numeric(df['age'].fillna(0),errors='coercs').isnull()]['age'].tolist()

good.csv

的输出
[]

bad.csv

的输出
['`']

这似乎是一个已知但尚未解决的错误(截至 9/2018):

https://github.com/great-expectations/great_expectations/issues/110

开发人员正在积极致力于改进行为:

  1. expect_column_values_to_be_of_type (the current expectation) has been cleaned up to now be closer to what we think people expect, and we are planning to rename it expect_column_values_to_be_stored_as_type

  2. We plan to introduce a new expectation expect_column_values_to_be_parseasble_as_type that accepts: string, float, int, bool (others?) and focuses on a more semantically meaningful understanding of the type (i.e. if a value is a string but the string is "1.0" then it will pass for string, float, and int).

希望很快就会有结果:

Implementation on 1 and 2 is about to start, but we're still open to suggestions...

问题是您的值实际上不是整数,而是字符串。当您使用 great_expectations.read_csv() 读取 csv 时,它会在内部使用 pandas.read_csv(),由于 ´,这会将 age column 中的数据默认为字符串。

方法 expect_column_values_to_be_of_type() 是非常基本的意思,它只会检查您的值是否是您要查找的类型 (isinstance()),而不是 "could" 是否是该类型。

作为实施新 expect_column_values_to_be_parseasble_as_type 之前的解决方法,我可以改用正则表达式期望来获得相同的结果:

my_df = ge.read_csv("bad.csv")
pattern = r'^\d+$'
result  = my_df.expect_column_values_to_match_regex('age',
                                                    pattern,
                                                    result_format={'result_format': 'COMPLETE'})

result
# In my case I'm only interested in where it went wrong
# print(result['result']['unexpected_list'])
# print(result['result']['unexpected_index_list'])

给出:

{'success': False,
 'result': {'element_count': 3,
  'missing_count': 0,
  'missing_percent': 0.0,
  'unexpected_count': 1,
  'unexpected_percent': 0.3333333333333333,
  'unexpected_percent_nonmissing': 0.3333333333333333,
  'partial_unexpected_list': ['`'],
  'partial_unexpected_index_list': [1],
  'partial_unexpected_counts': [{'value': '`', 'count': 1}],
  'unexpected_list': ['`'],
  'unexpected_index_list': [1]}}

请注意,如果要允许前导 + 或 - 您需要将模式更改为:

pattern = r'^[+-]?\d+$'