如何在DataFrame中转置包含行的列?

时间:2017-05-22 07:23:54

标签: java apache-spark apache-spark-sql

我使用Spark 1.6.0和Java 7.

我有以下输入数据集:

ColumnName

我想转置包含行的列,以便上面的数据框看起来像这样,列标题为Col1Col2Col3ColumnName(最初是ColumnName Col1 Col2 Col3 Param1 P1 P2 P6 Param2 P2 P4 P2 Param3 P3 P5 P9 列下的值。

public function getInventoryByParentId($parentId) {
    $inventory = Inventory::where('parentId', $parentId)->first();
    return response()->json($inventory->dataInv['subTask']);
}

2 个答案:

答案 0 :(得分:0)

以下解决方案如何? (花了我几个小时才完成,觉得有点累,让它更漂亮)。

给出以下输入:

val input = spark.
  read.
  option("header", true).
  option("delimiter", ",").
  csv("transpose.txt")
scala> input.show
+----------+------+------+------+
|ColumnName|Param1|Param2|Param3|
+----------+------+------+------+
|      Col1|    P1|    P2|    P3|
|      Col2|    P2|    P4|    P5|
|      Col3|    P6|    P2|    P9|
+----------+------+------+------+

我执行以下操作以转置包含行的列。

val fieldNames = input.schema.fieldNames
val cols = fieldNames.map(col(_))
val values = input.withColumn("values", struct(cols: _*))

val newCols = "ColumnName" +: input.select("ColumnName").as[String].collect
val fields = newCols.zipWithIndex.map { case (name, index) => input.schema(index).copy(name = name) }
import org.apache.spark.sql.types.StructType
val newSchema = StructType(fields)

val rows = input.drop("ColumnName").collect
import org.apache.spark.sql.Row
val newRows = fieldNames.
  drop(1).  // drop "ColumnName"
  zip(rows).
  map { case (f, r) => Row.merge(Row(f), r) }

val transposed = spark.createDataFrame(sc.parallelize(newRows), newSchema)

结果似乎符合要求:

scala> transposed.show
+----------+----+----+----+
|ColumnName|Col1|Col2|Col3|
+----------+----+----+----+
|    Param1|  P1|  P2|  P3|
|    Param2|  P2|  P4|  P5|
|    Param3|  P6|  P2|  P9|
+----------+----+----+----+

现在的问题是它的效果如何(如果有的话)? 只是适用于小型数据集。

答案 1 :(得分:0)

我们具有pivot函数来执行相同的操作。

Java版本:

Input:
+---------------+-------------+------+-------+
|       SensorId|   SensorName| Value|   Unit|
+---------------+-------------+------+-------+
|              1|     Humidity|    57|      p|
|              2|  Temperature|    25|      c|
|              1|     Humidity|    62|      p|
|              2|  Temperature|    27|      c|
|              1|     Humidity|    60|      p|
+---------------+-------------+------+-------+

df.groupBy("Sensor_Id","Unit")
  .pivot("SensorName").min("Value");

Output:
+---------------+-------------+---------+------------+
|       SensorId|         Unit| Humidity| Temperature|
+---------------+-------------+---------+------------+
|              1|            p|       57|        null|
|              2|            c|     null|          25|
|              1|            p|       62|        null|
|              2|            c|     null|          27|
|              1|            p|       60|        null|
+---------------+-------------+------+---------------+