当前位置: 首页 > 知识库问答 >
问题:

使用Spark Scala从字符串到数组[StructType]的模式转换

卫泉
2023-03-14

我有如下所示的示例数据,我需要使用spark scala代码将列(ABS,ALT)从字符串转换为数组[structType]。任何帮助都将不胜感激。

在UDF的帮助下,我能够从字符串转换为arrayType,但需要一些帮助来将这两列(ABS、ALT)的字符串转换为数组[structType]。

VIN         TT  MSG_TYPE ABS                           ALT
MSGXXXXXXXX 1   SIGL     [{"E":1569XXXXXXX,"V":0.0}] 
[{"E":156957XXXXXX,"V":0.0}]

df.currentSchema 
root
|-- VIN: string (nullable = true)
|-- TT: long (nullable = true)
|-- MSG_TYPE: string (nullable = true)
|-- ABS: string (nullable = true)
|-- ALT: string (nullable = true)

df。预期架构:

|-- VIN: string (nullable = true)
|-- TT: long (nullable = true)
|-- MSG_TYPE: string (nullable = true)
|-- ABS: array (nullable = true)
|    |-- element: struct (containsNull = true)
|    |    |-- E: long (nullable = true)
|    |    |-- V: long (nullable = true)
|-- ALT: array (nullable = true)
|    |-- element: struct (containsNull = true)
|    |    |-- E: long (nullable = true)
|    |    |-- V: double (nullable = true)

共有2个答案

郎鸿朗
2023-03-14

您可以使用udf解析Json并将其转换为结构数组。

首先,定义一个解析Json的函数(基于这个答案):

case class Data(E:String, V:Double)
class CC[T] extends Serializable { def unapply(a: Any): Option[T] = Some(a.asInstanceOf[T]) }
object M extends CC[Map[String, Any]]
object L extends CC[List[Any]]
object S extends CC[String]
object D extends CC[Double]

def toStruct(in: String): Array[Data] = {
  if( in == null || in.isEmpty) return new Array[Data](0)
  val result = for {
    Some(L(map)) <- List(JSON.parseFull(in))
    M(data) <- map
    S(e) = data("E")
    D(v) = data("V")
  } yield {
    Data(e, v)
  }
  result.toArray
}

此函数返回具有正确结构的数据对象数组。现在我们使用这个函数来定义自定义项

val ts: String => Array[Data] = toStruct(_)
import org.apache.spark.sql.functions.udf
val toStructUdf = udf(ts)

最后,我们调用udf(例如在select语句中):

val df = ...
val newdf = df.select('VIN, 'TT, 'MSG_TYPE, toStructUdf('ABS).as("ABS"), toStructUdf('ALT).as("ALT"))
newdf.printSchema()

输出:

root
 |-- VIN: string (nullable = true)
 |-- TT: string (nullable = true)
 |-- MSG_TYPE: string (nullable = true)
 |-- ABS: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- E: string (nullable = true)
 |    |    |-- V: double (nullable = false)
 |-- ALT: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- E: string (nullable = true)
 |    |    |-- V: double (nullable = false)
毕浩渺
2023-03-14

如果您尝试以下操作,它也会起作用:

import org.apache.spark.sql.types.{StructField, StructType, ArrayType, StringType}

val schema = ArrayType(StructType(Seq(StructField("E", LongType), StructField("V", DoubleType))))

val final_df = newDF.withColumn("ABS", from_json($"ABS", schema)).withColumn("ALT", from_json($"ALT", schema))

最终df。打印模式:

  root
 |-- VIN: string (nullable = true)
 |-- TT: string (nullable = true)
 |-- MSG_TYPE: string (nullable = true)
 |-- ABS: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- E: long (nullable = true)
 |    |    |-- V: double (nullable = false)
 |-- ALT: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- E: long (nullable = true)
 |    |    |-- V: double (nullable = false)
 类似资料:
  • 我正在制作一个模拟制表方法(Quine McCluskey)的程序,并试图将字符串格式的输入转换为整数格式,最后再转换为字符串(二进制格式)格式。 编辑:我忘了包括这个方法…

  • 我正在制作一个Android应用程序,它可以与蓝牙设备进行通信。我正在为选定的特征写一条特定的信息,如下所示: 我的转换函数如下所示: 我试图弄清楚为什么在这种情况下,我的转换输出是这样的: D/上传数据集:消息:�������������������� 这很奇怪,因为当我使用相同的转换函数来转换作为蓝牙通知接收到的值时,它工作得非常好。欢迎提出问题所在的任何建议

  • 问题内容: 我正在尝试从数据库中选择一个值,然后使用SELECT将其显示给用户。但是我不断收到此错误: 我以为可以解决此问题,但我仍然得到通知。这是我收到错误的代码部分: 我究竟做错了什么?我对PHP很陌生。 问题答案: 问题在于$ money是一个数组,您将其视为字符串或可以轻松转换为字符串的变量。您应该这样说:

  • 我遇到了这样一个java字符串,其中以下内容是错误的: 我想这是因为字符串构造函数默认将主体字节[]的编码视为UTF-8,我不是100%确定。我如何能够将此字符串存储在字节[]中,并能够稍后将其转换回来?我想我需要能够确定字节[]的编码方式。我该怎么做呢? 一些上下文:我需要字节[],以便压缩数据,将其存储在数据库中,然后解压缩并将未压缩的字节[]转换回原始字符串。这个字符串最初来自某个下载了网页

  • 我想将我的字符串转换为 LocalTime 格式 我收到错误: 线程“main”java.time.format中出现异常。DateTimeParseException:无法在索引0处分析文本“3:30” 预期产出: 上午3:30

  • 我正在写一个简单的井字游戏,需要在轮到他们的时候接受用户输入。玩家应该简单地提供一组坐标来放置他们的令牌(1,1)到(3,3)。我应该能够接受输入为“2 1”或“2,1”或“2,1”。所以我需要能够获取他们的字符串输入并提取两个数字中的每一个,而不管分隔符如何,并使用它们将他们的令牌分配给3x3数组中的指定单元格。 主要的问题是只能利用我们已经学过的东西(这是Java的第一节)。这是构建Java程