如何将DF转换为字符串/数组,然后再转换回DF?

时间:2019-10-24 08:45:28

标签: scala apache-spark apache-spark-sql

我要执行以下操作:

我有一个包含两列(ID,时间戳)和两个字符串的DataFrame,我想将其转换为另一种格式,字符串类型或Array [String]或Array [Row],但我没有真的很介意,但我想将其转换回DF。

我尝试了不同的事情:

  val aux= df.collect().map { row => row.toString() }
val distDataRDD = sc.parallelize(aux).toDF().show()

但是我只有一个名为“值”的列,它是原始DF中两列的串联

我也尝试过:

  val aux= df.collect().map { row => row.toString() }
val distDataRDD = sc.parallelize(aux).toDF("Id","timestamp").show()

但出现以下错误:

Exception in thread "main" java.lang.IllegalArgumentException: 
requirement failed: The number of columns doesn't match.
Old column names (1): value
New column names (2): Id, timestamp
    at scala.Predef$.require(Predef.scala:224)
    at org.apache.spark.sql.Dataset.toDF(Dataset.scala:448)
    at org.apache.spark.sql.DatasetHolder.toDF(DatasetHolder.scala:44)
    at example.tests$.main(tests.scala:60)
    at example.tests.main(tests.scala)

有什么想法吗?谢谢

2 个答案:

答案 0 :(得分:1)

您可以通过将 import 'package:flutter/material.dart'; main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Builder( builder: (context) => Scaffold( appBar: AppBar( title: Text("Page 1"), ), body: Center( child: Column( children: <Widget>[ MaterialButton( child: Text("Next Page"), onPressed: () { Navigator.push( context, MaterialPageRoute(builder: (context) => nextPage()), ); }, color: Colors.red, ) ], ), ), ), ), ); } } class nextPage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text("Page 2"), ), body: Center( child: Column( children: <Widget>[ MaterialButton( child: Text("Go Back!"), onPressed: () { Navigator.pop(context); }, color: Colors.red, ) ], ), ), ); } } 转换为Array[String]并使用RDD[Row]和提供的模式创建DF来实现。另一种选择是使用.createDataFrame创建DF,然后拆分值并将其选择为单独的列。

.toDF
  import spark.implicits._
  import org.apache.spark.sql.functions._

  val df = Seq(("1","2")).toDF()
  df.show()

  val aux = df.collect().map { row => row.mkString(",") }
  val aux2 = aux.map(s=>RowFactory.create(s.split(","):_*))

  val schema = new (StructType)
    .add("id","string")
    .add("timestamp","string")

  val df2 = spark.createDataFrame(sc.parallelize(aux2),schema)
  df2.show()

  // another option

  aux.toSeq.toDF("val")
    .select(split('val,",").as("arr"))
    .select('arr.getItem(0).as("id"),'arr.getItem(1).as("timestamp"))
    .show()

答案 1 :(得分:0)

您可以使用spark内置函数来执行此操作。

val df = Seq(
  ("a", "1"),
  ("b", "2")
).toDF()

df
  .select(org.apache.spark.sql.functions.array($"_1", $"_2"))
  .show()

此处,array函数将值放置在每一行的数组中的“ _1”列和“ _2”列中。 您可以查看spark SQL函数以找到符合您需求的函数。如果找不到一个,则可能必须创建一个用户定义的函数(UDF),但不建议使用此函数,因为内置函数会得到更优化。