如何在scala中转换一个数组中的1列参数和1值参数?

oknrviil  于 2023-10-18  发布在  Scala
关注(0)|答案(1)|浏览(127)

我很难从一个包含列名的arg和一个包含scala值的arg创建一个框架。
它无法识别spark. toDataFrame(dataClient).toDF(columns._*)

val dataClient = args(0).split(",").map(_.trim)
val column = args(1).split(",").map(_.trim)

val dataClient = Seq(dataClient)
val df: DataFrame = spark.createDataFrame(dataClient).toDF(columns. _*)

我能用另一种方式来做而不需要一个库吗?
记住我不能使用云,所以导入服务非常有限。
一种将列参数和另一个值参数转换为嵌套框架的方法

0g0grzrc

0g0grzrc1#

根据Gaël J的评论,你的意思是在列中使用“.”。**,事实上你c+p'd看起来是这样的。语法是:**not ._*。
还有:

val dataClient = args(0).split(",").map(_.trim)
val column = args(1).split(",").map(_.trim)

val dataClient = Seq(dataClient)
val df: DataFrame = spark.createDataFrame(dataClient).toDF(columns. _*)

第1行将dataClient声明为Array[String],第3行尝试使用单个条目将dataClient重新声明为Seq[Array[String]]。声明列,然后使用列“% s”。
最后,DataFrame已经创建了一个DataFrame,所以toDF在这里没有意义。
目前还不清楚你想做什么,但这段代码,即使经过这些更正,但我认为它是这样的:

import spark.implicits._
val args = Seq("a,b,c,d","colname")

val dataClient = args(0).split(",").map(_.trim).toSeq
val column = args(1).trim

val df: DataFrame = dataClient.toDF(column)
df.show()

产生:

+-------+
|colname|
+-------+
|      a|
|      b|
|      c|
|      d|
+-------+

“import spark.implicits._”将调用DF所需的所有隐式机制带入范围,“.toSeq”允许该机制看到Seq[String]而不是Array[String],以便toDF可以工作。

  • 如果 * 你试图通过它获得多个列,它并不那么简单,因为如果你使用这样的东西,每一个“行”都将被视为一个数组:
import spark.implicits._
val args = Seq("a,b, c, d | e,f ,g, h ","col1, col2, col3 , col4")

val dataClient = args(0).split("\\|").map(_.trim).map(_.split(",").map(_.trim) ).toSeq
val columns = args(1).split(",").map(_.trim)

val df: DataFrame = dataClient.toDF(columns :_ *)
df.show()

其产生:

java.lang.IllegalArgumentException: requirement failed: The number of columns doesn't match.
Old column names (1): value
New column names (4): col1, col2, col3, col4

    at scala.Predef$.require(Predef.scala:281)

要做到这一点,需要直接生成行:

val args = Seq("a,b, c, d | e,f ,g, h ","col1, col2, col3 , col4")

val columns = args(1).split(",").map(_.trim)
val schema = StructType(columns.map(c => StructField(c, StringType)))

val dataClient = args(0).split("\\|").map(_.trim).map{ raw =>
  val rawSeq =
    raw.split(",").map(_.trim)
  new GenericRowWithSchema(rawSeq.asInstanceOf[ Array[Any] ], schema) : Row
}.toSeq

implicit val rowEnc = RowEncoder(schema)

val df = spark.createDataset(dataClient)
df.show()

导致:

+----+----+----+----+
|col1|col2|col3|col4|
+----+----+----+----+
|   a|   b|   c|   d|
|   e|   f|   g|   h|
+----+----+----+----+

但有几件事你应该避免:

new GenericRowWithSchema(rawSeq.asInstanceOf[ Array[Any] ], schema) : Row

虽然不是Spark的“内部”,但绝对不是为了让你这样使用Spark。
如果这是一个学习经验,我建议制作一个csv文件并阅读,而不是试图构建这样的架构,如果不是,那么我建议您使用像parquet这样的文件交换,它包括架构,并且不会在您的领域中实际需要一个“,”(或|或任何你试图用作分隔符的东西)。如果它真的必须是文本,那么看看json,它也允许传入一些结构(尽管不是带有非字符串键的map)。

相关问题