Repository: great-expectations/great_expectations

Issue:
Use cleaner solution for non-truncating division in python 2
Prefer `from __future__ import division` to `1.*x/y`


Discussion:
Done inline during improve_partitions push.

Resolving patch:
diff --git a/great_expectations/expectations/metrics/column_aggregate_metrics/column_value_counts.py b/great_expectations/expectations/metrics/column_aggregate_metrics/column_value_counts.py
--- a/great_expectations/expectations/metrics/column_aggregate_metrics/column_value_counts.py
+++ b/great_expectations/expectations/metrics/column_aggregate_metrics/column_value_counts.py
@@ -157,15 +157,23 @@ def _spark(
         value_counts_df: pyspark_sql_DataFrame = (
             df.select(column).where(F.col(column).isNotNull()).groupBy(column).count()
         )
+
         if sort == "value":
             value_counts_df = value_counts_df.orderBy(column)
         elif sort == "count":
             value_counts_df = value_counts_df.orderBy(F.desc("count"))
+
         value_counts: List[pyspark_sql_Row] = value_counts_df.collect()
+
         # Numpy does not always infer the correct DataTypes for Spark df, so we cannot use vectorized approach.
-        values: Any
-        counts: int
-        values, counts = zip(*value_counts)
+        values: List[Any]
+        counts: List[int]
+        if len(value_counts) > 0:
+            values, counts = zip(*value_counts)
+        else:
+            values = []
+            counts = []
+
         series = pd.Series(
             counts,
             index=pd.Index(data=values, name="value"),


Test patch:
diff --git a/tests/expectations/metrics/test_core.py b/tests/expectations/metrics/test_core.py
--- a/tests/expectations/metrics/test_core.py
+++ b/tests/expectations/metrics/test_core.py
@@ -3924,22 +3924,30 @@ def test_median_metric_spark(spark_session):
 
 
 @pytest.mark.integration
-def test_value_counts_metric_spark(spark_session):
-    engine: SparkDFExecutionEngine = build_spark_engine(
-        spark=spark_session,
-        df=pd.DataFrame(
-            {"a": [1, 2, 1, 2, 3, 3, None]},
-        ),
-        batch_id="my_id",
-    )
+def test_value_counts_metric_pd():
+    engine = build_pandas_engine(pd.DataFrame({"a": [1, 2, 1, 2, 3, 3]}))
+
+    metrics: dict = {}
+
+    table_columns_metric: MetricConfiguration
+    results: dict
+
+    table_columns_metric, results = get_table_columns_metric(engine=engine)
+    metrics.update(results)
 
     desired_metric = MetricConfiguration(
         metric_name="column.value_counts",
         metric_domain_kwargs={"column": "a"},
         metric_value_kwargs={"sort": "value", "collate": None},
+        metric_dependencies={
+            "table.columns": table_columns_metric,
+        },
     )
 
-    metrics = engine.resolve_metrics(metrics_to_resolve=(desired_metric,))
+    results = engine.resolve_metrics(
+        metrics_to_resolve=(desired_metric,), metrics=metrics
+    )
+    metrics.update(results)
     assert pd.Series(index=[1, 2, 3], data=[2, 2, 2]).equals(metrics[desired_metric.id])
 
 
@@ -3976,31 +3984,45 @@ def test_value_counts_metric_sa(sa):
 
 
 @pytest.mark.integration
-def test_value_counts_metric_pd():
-    engine = build_pandas_engine(pd.DataFrame({"a": [1, 2, 1, 2, 3, 3]}))
-
-    metrics: dict = {}
-
-    table_columns_metric: MetricConfiguration
-    results: dict
+def test_value_counts_metric_spark(spark_session):
+    from great_expectations.expectations.metrics.import_manager import sparktypes
 
-    table_columns_metric, results = get_table_columns_metric(engine=engine)
-    metrics.update(results)
+    engine: SparkDFExecutionEngine = build_spark_engine(
+        spark=spark_session,
+        df=pd.DataFrame(
+            {
+                "a": [1, 2, 1, 2, 3, 3, None],
+                "b": [None, None, None, None, None, None, None],
+            },
+        ),
+        schema=sparktypes.StructType(
+            [
+                sparktypes.StructField("a", sparktypes.FloatType(), True),
+                sparktypes.StructField("b", sparktypes.NullType(), True),
+            ]
+        ),
+        batch_id="my_id",
+    )
 
     desired_metric = MetricConfiguration(
         metric_name="column.value_counts",
         metric_domain_kwargs={"column": "a"},
         metric_value_kwargs={"sort": "value", "collate": None},
-        metric_dependencies={
-            "table.columns": table_columns_metric,
-        },
     )
 
-    results = engine.resolve_metrics(
-        metrics_to_resolve=(desired_metric,), metrics=metrics
+    metrics = engine.resolve_metrics(metrics_to_resolve=(desired_metric,))
+    assert pd.Series(index=[1.0, 2.0, 3.0, np.nan], data=[2, 2, 2, 1]).equals(
+        metrics[desired_metric.id]
     )
-    metrics.update(results)
-    assert pd.Series(index=[1, 2, 3], data=[2, 2, 2]).equals(metrics[desired_metric.id])
+
+    desired_metric = MetricConfiguration(
+        metric_name="column.value_counts",
+        metric_domain_kwargs={"column": "b"},
+        metric_value_kwargs={"sort": "value", "collate": None},
+    )
+
+    metrics = engine.resolve_metrics(metrics_to_resolve=(desired_metric,))
+    assert pd.Series(index=[], data=[]).equals(metrics[desired_metric.id])
 
 
 @pytest.mark.integration