如何使用 toDF() 将自定义 Java 类对象的 RDD 转换为 DataFrame?

Posted

技术标签:

【中文标题】如何使用 toDF() 将自定义 Java 类对象的 RDD 转换为 DataFrame?【英文标题】:How to convert RDD of custom Java class objects to a DataFrame with toDF()? 【发布时间】:2017-04-27 17:23:51 【问题描述】:

我正在尝试使用toDF() 将 Spark RDD 转换为 Spark SQL 数据帧。我已经成功使用过这个函数很多次了,但是在这种情况下我得到了一个编译器错误:

error: value toDF is not a member of org.apache.spark.rdd.RDD[com.example.protobuf.SensorData]

下面是我的代码:

// SensorData is an auto-generated class
import com.example.protobuf.SensorData
def loadSensorDataToRdd : RDD[SensorData] = ???

object MyApplication 
  def main(argv: Array[String]): Unit = 

    val conf = new SparkConf()
    conf.setAppName("My application")
    conf.set("io.compression.codecs", "com.hadoop.compression.lzo.LzopCodec")
    val sc = new SparkContext(conf)

    val sqlContext = new org.apache.spark.sql.SQLContext(sc)
    import sqlContext.implicits._

    val sensorDataRdd = loadSensorDataToRdd()
    val sensorDataDf = sensorDataRdd.toDF() // <-- CAUSES COMPILER ERROR
  

我猜测问题出在 SensorData 类上,它是一个从 Protocol Buffer 自动生成的 Java 类。为了将 RDD 转换为数据帧,我该怎么做?

【问题讨论】:

***.com/questions/29383578/… tripSummary 是在哪里创建的? @Zzrot:抱歉,这是一个错字。此行导致编译器错误:sensorDataRdd().toDF(). .toDF() 期望 sensorDataRdd 的数据类型为 org.apache.spark.rdd.RDD[Row] 而不是 SensorData。 ***.com/a/40625586/6576230 可能会有所帮助。 :) @Zzrot:我阅读了另一个 *** 问题的链接。我不明白接下来我应该尝试什么。 【参考方案1】:

编译错误的原因是范围内没有Encoder 可以将带有com.example.protobuf.SensorDataRDD 转换为com.example.protobuf.SensorDataDataset

Encoders(准确的说是ExpressionEncoders)用于将InternalRow对象按照schema(通常是case class或者Java bean)转换成JVM对象。

希望您可以使用org.apache.spark.sql.Encoders 对象的bean 方法为自定义Java 类创建Encoder

为 T 类型的 Java Bean 创建一个编码器。

类似于以下内容:

import org.apache.spark.sql.Encoders
implicit val SensorDataEncoder = Encoders.bean(classOf[com.example.protobuf.SensorData])

如果SensorData 使用不受支持的类型,您必须将map RDD[SensorData] 转换为一些更简单类型的RDD,例如字段的元组,然后才期望 toDF 工作。

【讨论】:

+1 将自定义对象 RDD 转换为 Dataset(又名 DataFrame)不是正确的答案,但通过编码器转到 Dataset 是正确的答案。具有自定义对象的数据集是理想的,因为您会遇到编译错误和催化剂优化器性能提升。 当然! @Garren 不会说得更好,但这不在这个问题范围内,因此甚至都懒得提它。好点,不过!谢谢。如果我看到评论的赞成票(你的或我的),我可能会添加你的评论;-) 问题是关于将自定义对象 RDD 转换为 Dataframe,这将是一个愚蠢的转换,所以我觉得澄清您使用 Dataset 而不是特定 DataFrame 请求的意图与问题范围 @JacekLaskowski:请添加任何可以帮助我(和其他人)的其他信息。 @***user2010 DataFrame 确实是 Dataset&lt;Row&gt; 的别名 - Row 是 通用行对象 而不是自定义类对象(例如 SensorData)。您引用的那本出色的书是由回答您问题的那个人写的;)。我找不到想要显示 RDD/DF/DS 运行/编译时间故障的图像,但获得亚军:i.stack.imgur.com/3rF6p.png***.com/questions/35424854/…***.com/questions/34654145/…

以上是关于如何使用 toDF() 将自定义 Java 类对象的 RDD 转换为 DataFrame?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用处理 Java 库将自定义形状数组和字符串数组合并到 JSON 对象中

如何以编程方式将自定义 Java 视图类加载到 RelativeLayout

Azure Cosmos SQL API - 如何将自定义对象存储为 @PartitionKey

为啥委托方法需要将自定义类托管对象上下文的内容保存在委托类托管对象上下文中?

无法实现 operator==() 将自定义类对象与 QString 进行比较

将自定义组件指令绑定到 for 循环中的对象