繁体   English   中英

从rdd目标文件创建数据框

[英]Create dataframe from rdd objectfile

从保存为目标文件的RDD创建ddf的方法是什么。 我想加载RDD,但没有Java对象,只有一个要用作ddf模式的structtype。

我尝试检索为行

    val myrdd = sc.objectFile[org.apache.spark.sql.Row]("/home/bipin/"+name)

但是我明白了

java.lang.ClassCastException:[Ljava.lang.Object; 无法转换为org.apache.spark.sql.Row

有没有办法做到这一点。

编辑

据我了解,我必须将rdd读取为对象数组并将其转换为行。 如果任何人都可以为此提供一种方法,那将是可以接受的。

如果您有一个对象数组,则只需对任何一个数组使用行应用方法。 在代码中将是这样的:

val myrdd = sc.objectFile[Array[Object]]("/home/bipin/"+name).map(x => Row(x))

编辑

您是严格的@ user568109,这将创建一个仅具有一个字段的数据框,该字段将是一个数组,用于解析整个数组,您必须执行以下操作:

val myrdd = sc.objectFile[Array[Object]]("/home/bipin/"+name).map(x => Row.fromSeq(x.toSeq))

正如@ user568109所说,还有其他方法可以做到这一点:

val myrdd = sc.objectFile[Array[Object]]("/home/bipin/"+name).map(x => Row(x:_*))

不管您选择哪一个,因为两者都是相同代码的包装:

  /**
   * This method can be used to construct a [[Row]] with the given values.
   */
   def apply(values: Any*): Row = new GenericRow(values.toArray)

  /**
   * This method can be used to construct a [[Row]] from a [[Seq]] of values.
   */
   def fromSeq(values: Seq[Any]): Row = new GenericRow(values.toArray)

让我补充一些解释,

假设您有一个包含3列(项目,类别,价格)的mysql表食品杂货,其内容如下

+------------+---------+----------+-------+
| grocery_id | item    | category | price |
+------------+---------+----------+-------+
|          1 | tomato  | veg      |  2.40 |
|          2 | raddish | veg      |  4.30 |
|          3 | banana  | fruit    |  1.20 |
|          4 | carrot  | veg      |  2.50 |
|          5 | apple   | fruit    |  8.10 |
+------------+---------+----------+-------+
5 rows in set (0.00 sec)

现在,在您想要阅读的Spark中,您的代码将如下所示

val groceryRDD = new JdbcRDD(sc, ()=> DriverManager.getConnection(url,uname,passwd), "select item,price from grocery limit ?,?",1,10,2,r => r.getString("item")+"|"+r.getString("price"))

注意:在上面的语句中,我将ResultSet转换为String r => r.getString(“ item”)+“ |” + r.getString(“ price”)

所以我的JdbcRDD将是

groceryRDD: org.apache.spark.rdd.JdbcRDD[String] = JdbcRDD[29] at JdbcRDD at <console>:21

现在保存。

groceryRDD.saveAsObjectFile("/user/cloudera/jdbcobject")

回答你的问题

在读取目标文件时,您需要编写如下内容,

val newJdbObjectFile = sc.objectFile[String]("/user/cloudera/jdbcobject")

以盲目方式,仅替换要保存的RDD的Parameter类型

就我而言,杂货RDD的类型参数为String,因此我使用了相同的参数

更新:

就您而言,正如jlopezmat所述,您需要使用Array [Object]

在这里,RDD的每一行都是Object ,但是由于您已经使用ObjectArray进行了转换,因此每行及其内容将再次保存为Array,

即,就我而言,如果保存在RDD上方,如下所示,

val groceryRDD = new JdbcRDD(sc, ()=> DriverManager.getConnection(url,uname,passwd), "select item,price from grocery limit ?,?",1,10,2,r => JdbcRDD.resultSetToObjectArray(r))

当我阅读相同的内容并收集数据时

val newJdbcObjectArrayRDD = sc.objectFile[Array[Object]]("...")
val result = newJdbObjectArrayRDD.collect

结果将为Array [Array [Object]]类型

result: Array[Array[Object]] = Array(Array(raddish, 4.3), Array(banana, 1.2), Array(carrot, 2.5), Array(apple, 8.1))

您可以根据列定义来解析以上内容。

请让我知道它是否回答了您的问题

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM