Skip to content
This repository was archived by the owner on May 9, 2024. It is now read-only.

Commit c9fa870

Browse files
JoshRosenrxin
authored andcommitted
[SPARK-7687] [SQL] DataFrame.describe() should cast all aggregates to String
In `DataFrame.describe()`, the `count` aggregate produces an integer, the `avg` and `stdev` aggregates produce doubles, and `min` and `max` aggregates can produce varying types depending on what type of column they're applied to. As a result, we should cast all aggregate results to String so that `describe()`'s output types match its declared output schema. Author: Josh Rosen <[email protected]> Closes apache#6218 from JoshRosen/SPARK-7687 and squashes the following commits: 146b615 [Josh Rosen] Fix R test. 2974bd5 [Josh Rosen] Cast to string type instead f206580 [Josh Rosen] Cast to double to fix SPARK-7687 307ecbf [Josh Rosen] Add failing regression test for SPARK-7687
1 parent c2437de commit c9fa870

File tree

3 files changed

+19
-14
lines changed

3 files changed

+19
-14
lines changed

R/pkg/inst/tests/test_sparkSQL.R

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -757,12 +757,12 @@ test_that("parquetFile works with multiple input paths", {
757757
test_that("describe() on a DataFrame", {
758758
df <- jsonFile(sqlCtx, jsonPath)
759759
stats <- describe(df, "age")
760-
expect_true(collect(stats)[1, "summary"] == "count")
761-
expect_true(collect(stats)[2, "age"] == 24.5)
762-
expect_true(collect(stats)[3, "age"] == 5.5)
760+
expect_equal(collect(stats)[1, "summary"], "count")
761+
expect_equal(collect(stats)[2, "age"], "24.5")
762+
expect_equal(collect(stats)[3, "age"], "5.5")
763763
stats <- describe(df)
764-
expect_true(collect(stats)[4, "name"] == "Andy")
765-
expect_true(collect(stats)[5, "age"] == 30.0)
764+
expect_equal(collect(stats)[4, "name"], "Andy")
765+
expect_equal(collect(stats)[5, "age"], "30")
766766
})
767767

768768
unlink(parquetPath)

sql/core/src/main/scala/org/apache/spark/sql/DataFrame.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1063,7 +1063,7 @@ class DataFrame private[sql](
10631063

10641064
val ret: Seq[Row] = if (outputCols.nonEmpty) {
10651065
val aggExprs = statistics.flatMap { case (_, colToAgg) =>
1066-
outputCols.map(c => Column(colToAgg(Column(c).expr)).as(c))
1066+
outputCols.map(c => Column(Cast(colToAgg(Column(c).expr), StringType)).as(c))
10671067
}
10681068

10691069
val row = agg(aggExprs.head, aggExprs.tail: _*).head().toSeq
@@ -1077,9 +1077,9 @@ class DataFrame private[sql](
10771077
statistics.map { case (name, _) => Row(name) }
10781078
}
10791079

1080-
// The first column is string type, and the rest are double type.
1080+
// All columns are string type
10811081
val schema = StructType(
1082-
StructField("summary", StringType) :: outputCols.map(StructField(_, DoubleType))).toAttributes
1082+
StructField("summary", StringType) :: outputCols.map(StructField(_, StringType))).toAttributes
10831083
LocalRelation(schema, ret)
10841084
}
10851085

sql/core/src/test/scala/org/apache/spark/sql/DataFrameSuite.scala

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -370,14 +370,14 @@ class DataFrameSuite extends QueryTest {
370370
("Amy", 24, 180)).toDF("name", "age", "height")
371371

372372
val describeResult = Seq(
373-
Row("count", 4, 4),
374-
Row("mean", 33.0, 178.0),
375-
Row("stddev", 16.583123951777, 10.0),
376-
Row("min", 16, 164),
377-
Row("max", 60, 192))
373+
Row("count", "4", "4"),
374+
Row("mean", "33.0", "178.0"),
375+
Row("stddev", "16.583123951777", "10.0"),
376+
Row("min", "16", "164"),
377+
Row("max", "60", "192"))
378378

379379
val emptyDescribeResult = Seq(
380-
Row("count", 0, 0),
380+
Row("count", "0", "0"),
381381
Row("mean", null, null),
382382
Row("stddev", null, null),
383383
Row("min", null, null),
@@ -388,6 +388,11 @@ class DataFrameSuite extends QueryTest {
388388
val describeTwoCols = describeTestData.describe("age", "height")
389389
assert(getSchemaAsSeq(describeTwoCols) === Seq("summary", "age", "height"))
390390
checkAnswer(describeTwoCols, describeResult)
391+
// All aggregate value should have been cast to string
392+
describeTwoCols.collect().foreach { row =>
393+
assert(row.get(1).isInstanceOf[String], "expected string but found " + row.get(1).getClass)
394+
assert(row.get(2).isInstanceOf[String], "expected string but found " + row.get(2).getClass)
395+
}
391396

392397
val describeAllCols = describeTestData.describe()
393398
assert(getSchemaAsSeq(describeAllCols) === Seq("summary", "age", "height"))

0 commit comments

Comments
 (0)