Features and enhancements done #299
Conversation
Features: > Support Spark's DateType and TimestampType > min and max analysis on date time fields
> New constraints for Spark's DateType and Timestamp Types
> BigDecimal State and Metric Support in Min, Max, Sum and Mean Analyzers
> 'isContained' is made available for all Numeric Types and Char
> Analyzer - DateTimeDistribution for analyzing distributions metrics (count, ratio) over some time intervals
|
Thanks! Could you look at the CI failures and fix them? |
|
Hi, is this feature now available? |
sorry for the late reply. Ill work on it. |
|
This is valuable feature you've added @Yash0215. awesome. Looking forward to using it. |
|
Can I assist in anyway @yash021? I'm looking to utilise this functionality asap. |
|
please recommend if any changes are needed. |
|
So the two enhancements implemented in this PR are essentially orthogonal, right ? If so I'd recommend we split them into separate PRs and focus on each. |
|
Yes, that would make a lot of sense. |
|
Hello @Yash0215 @sscdotopen, were there furthur developments on this work? If not, I can volunteer to take it forward. |
|
FWIW, I forked this project and am actively developing it afterwards. I'm also thinking of announcing it as an active fork of this project somewhere (maybe as an issue for this repo) in the near future. |
|
Hi, thanks so much for introducing all these changes. Unfortunately, we currently don't have availability to give this a proper review. Will keep this PR in the backlog for now. If you have the opportunity to submit a couple of smaller reviews that would be great. It's hard to find the time to do big reviews and a few smaller PRs could help us understand the main ideas and make progress on this. |
|
@Yash0215 Please get back to us on this if you get the chance. We are considering closing this PR soon. |
|
Any update on this? to improve deequ for handling of timestamp/date support? |
|
This PR is quite big with multiple unrelated changes making review hard. Chunk this into multiple smaller PR should be a good start. I am interested in timestamp/date support |
| def metricValue(): Double | ||
| } | ||
|
|
||
| /** A state which produces a BigDecimalValued metric */ |
There was a problem hiding this comment.
The BigDecimalValuedState trait's metricValue() returns java.math.BigDecimal which can be null (as seen in BigDecimalMeanState.metricValue() when count is 0). This is unsafe — callers like BigDecimalScanShareableAnalyzer.computeMetricFrom wrap it in Success(theState.metricValue()), which would produce Success(null) rather than a proper Failure. Consider returning Option[BigDecimal] or handling the null/zero-count case before wrapping in Success.
| @@ -52,6 +54,11 @@ trait DoubleValuedState[S <: DoubleValuedState[S]] extends State[S] { | |||
| def metricValue(): Double | |||
There was a problem hiding this comment.
The Analyzer trait has lost its extends Serializable declaration in this diff. The original code has trait Analyzer[S <: State[_], +M <: Metric[_]] extends Serializable, but the new code shows just trait Analyzer[S <: State[_], +M <: Metric[_]]. This will break serialization for Spark jobs that serialize analyzers (e.g., for broadcast or closure capture).
| Seq.empty | ||
| } | ||
| } | ||
|
|
There was a problem hiding this comment.
NumMatchesAndCount has lost its override val fullColumn: Option[Column] = None field and the FullColumn trait mixin compared to the existing code. This will break row-level results for Completeness, Compliance, PatternMatch, and other analyzers that rely on NumMatchesAndCount carrying a fullColumn.
| override def aggregationFunctions(): Seq[Column] = { | ||
| sum(conditionalSelection(column, where)) :: | ||
| count(conditionalSelection(column, where)).cast(LongType) :: Nil | ||
| } |
There was a problem hiding this comment.
BigDecimalMeanState.metricValue() returns null when count == 0L. This will result in Success(null) being stored in the metric, which will cause NPEs downstream (e.g., when flattening the metric or running assertions). Should return a failure or handle this case in computeMetricFrom.
|
|
||
| override def filterCondition: Option[String] = where | ||
| } | ||
|
|
There was a problem hiding this comment.
The refactored Maximum analyzer has lost the FullColumn trait on MaxState, the analyzerOptions parameter, the augmented outcome logic (criterion with conditionalSelectionWithAugmentedOutcome), and the computeMetricFrom override for the WHERE-filters-all-rows case. This is a regression that breaks row-level results and filtered-row handling for hasMax checks.
|
|
||
| override def filterCondition: Option[String] = where | ||
| } | ||
|
|
There was a problem hiding this comment.
Same regression as Maximum: the refactored Minimum analyzer has lost the FullColumn trait on MinState, the analyzerOptions parameter, the augmented outcome logic, and the computeMetricFrom override. This breaks row-level results and filtered-row handling for hasMin checks.
| column: String, | ||
| allowedValues: Array[String], | ||
| allowedValues: Array[T], | ||
| assertion: Double => Boolean, |
There was a problem hiding this comment.
The isContainedIn signature has been changed from Array[String] to generic Array[T], but the existing overloads with Array[String] that take different parameter combinations still exist. After erasure, Array[T] and Array[String] both become Array[Object], which will cause compilation errors due to ambiguous overloaded methods. The generic version should be a separate method name or the existing overloads need to be removed/consolidated.
|
|
||
|
|
||
| import com.amazon.deequ.analyzers.KLLSketch | ||
| import com.amazon.deequ.analyzers.catalyst.DateTimeAggregation |
There was a problem hiding this comment.
The import import com.amazon.deequ.analyzers.catalyst.DateTimeAggregation was added but the original import import com.amazon.deequ.analyzers.KLLSketch was removed. However, KLLSketch is not used in this file (it's referenced via StatefulKLLSketch), so this removal is fine. But note that DateTimeAggregation is in the same package (com.amazon.deequ.analyzers.catalyst) — this import is unnecessary since the file is in org.apache.spark.sql package, not com.amazon.deequ.analyzers.catalyst. Actually, looking more carefully, the file declares package org.apache.spark.sql so the import IS needed. No issue here.
| ifNoNullsIn(result, offset) { _ => | ||
| DateTimeDistributionState( | ||
| DateTimeDistributionState.computeStateFromResult(Map.empty[Long, Long] ++ result.getMap(0), | ||
| DateTimeDistribution.getDateTimeAggIntervalValue(interval))) |
There was a problem hiding this comment.
DateTimeDistribution extends ScanShareableAnalyzer but does not extend Analyzer with Serializable. Since the base Analyzer trait lost extends Serializable in this PR's changes to Analyzer.scala, this class won't be serializable, which will cause failures when Spark tries to serialize it for distributed execution.
| val data = ordersAsDataframe(session, | ||
| Order(1, new BigDecimal(213.2132), Timestamp.valueOf("2020-02-15 07:15:00")), | ||
| Order(2, new BigDecimal(43.21324432876), Timestamp.valueOf("2020-02-15 07:45:00.999")), | ||
| Order(3, new BigDecimal(56.8881238823888), Timestamp.valueOf("2020-02-15 08:15:49.786")), |
There was a problem hiding this comment.
new BigDecimal(213.2132) uses the BigDecimal(double) constructor which is well-known to produce unexpected results due to floating-point representation (e.g., new BigDecimal(0.1) gives 0.1000000000000000055511151231257827021181583404541015625). Use new BigDecimal("213.2132") or BigDecimal.valueOf(213.2132) instead.
New Features:
1.
A Date Time Distribution analyzer for analyzing the distribution of the records based on 'DateType' or 'TimestampType' feature within fixed time intervals.
files changed/created:
DateTimeDistribution.scala
DateTimeAggregation.scala
DeequFunctions.scala
...
6 new Constraints added covering more use cases for DateTime quality checks:
files changed/created:
Check.scala
Constraint.scala
Constraint 'isContainedIn' is now supports more Scala Numeric Types
files changed/created:
Check.scala
Enahancements:
Issue: Timestamp support Timestamp support #47
New State and Metric is implemented for this enhancement since previous analyzer only support Double Metric and Standard analyzer. a new abstract analyzer for timestamp analysis is implemented.
files changed/created:
MinimumDateTime.scala, MaximumDateTime.scala (for new analyzer implementation)
Analyzer.scala
Analyzer for Precision and Scale of BigDecimals Analyzer for Precision and Scale of BigDecimals #46
New State and Metric is implemented. Also new analyzers that provides precision and scale of Spark's 'DecimalType'.
files changed/created:
Minimum.scala, Maximum.scala, Sum.scala, Mean.scala (for new analyzer implementation)
Analyzer.scala
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.