在Apache Spark中将Dataframe的列值提取为List

SH *_* Y. 73 scala apache-spark apache-spark-sql

我想将数据帧的字符串列转换为列表.我可以从DataframeAPI 找到的是RDD,所以我尝试先将其转换回RDD,然后将toArray函数应用于RDD.在这种情况下,长度和SQL工作就好了.但是,我从RDD得到的结果在每个元素周围都有方括号[A00001].我想知道是否有适当的方法将列转换为列表或删除方括号的方法.

任何建议,将不胜感激.谢谢!

Nie*_*and 97

这应该返回包含单个列表的集合:

dataFrame.select("YOUR_COLUMN_NAME").rdd.map(r => r(0)).collect()
Run Code Online (Sandbox Code Playgroud)

如果没有映射,您只需获得一个Row对象,该对象包含数据库中的每一列.

请记住,这可能会为您提供任何类型的列表.如果要指定结果类型,可以在r => r(0).asInstanceOf[YOUR_TYPE]映射中使用.asInstanceOf [YOUR_TYPE]

PS由于自动转换你可以跳过.rdd部分.

  • 与DF/RDD相反的scala List是一个非分布式实体 - 因此,如果您想要一个List,则必须在一个节点上收集所有内容(在这种情况下,这是驱动程序).所以不,没有其他方法可以获取List而不是将所有内容从执行程序拉到驱动程序. (3认同)
  • 关于`asInstanceOf`的提醒,避免类型不匹配 (2认同)
  • 由于一些奇怪的原因,它反过来工作(Spark 2.1.0)`collect().map(r => r(0))` - 这个顺序有什么缺点吗? (2认同)

mrs*_*vas 51

使用Spark 2.x和Scala 2.11

我想到了将特定列的值转换为List的3种可能方法

所有方法的通用代码片段

import org.apache.spark.sql.SparkSession

val spark = SparkSession.builder.getOrCreate    
import spark.implicits._ // for .toDf() method

val df = Seq(
    ("first", 2.0),
    ("test", 1.5),
    ("choose", 8.0)
  ).toDF("id", "val")
Run Code Online (Sandbox Code Playgroud)

方法1

df.select("id").collect().map(_(0)).toList
// res9: List[Any] = List(one, two, three)
Run Code Online (Sandbox Code Playgroud)

现在发生了什么?我们正在向collect()每个记录中的Driver with 和pick元素0 收集数据.

这不是一个很好的方法,让我们用下一个方法来改进它.


方法2

df.select("id").rdd.map(r => r(0)).collect.toList 
//res10: List[Any] = List(one, two, three)
Run Code Online (Sandbox Code Playgroud)

它怎么样更好?我们在工人之间分配了地图转换负载而不是单个驱动程序.

我知道rdd.map(r => r(0))你看起来并不优雅.那么,让我们在下一个方法中解决它.


方法3

df.select("id").map(r => r.getString(0)).collect.toList 
//res11: List[String] = List(one, two, three)
Run Code Online (Sandbox Code Playgroud)

这里我们没有将DataFrame转换为RDD.由于DataFrame中的编码器问题,map因此它不会接受r => r(0)(或_(0))作为前一种方法.所以最终使用r => r.getString(0)它将在下一版本的Spark中解决.

结论

所有选项都提供相同的输出,但2和3是有效的,最后第3个是有效和优雅的(我认为).

Databricks笔记本链接将于2017年5月20日起提供至6个月


abb*_*obh 17

我知道给出的答案是scala的假设,所以我只是提供一些Python代码片段以防PySpark用户好奇.语法类似于给定的答案,但为了正确弹出列表,我实际上必须在映射函数中第二次引用列名,而我不需要select语句.

即一个DataFrame,包含一个名为"Raw"的列

要将"Raw"中的每个行值合并为一个列表,其中每个条目都是"Raw"的行值,我只需使用:

MyDataFrame.rdd.map(lambda x: x.Raw).collect()
Run Code Online (Sandbox Code Playgroud)

  • 这给出了Row对象的列表.如果您想要一个值列表怎么办? (3认同)

kan*_*elc 5

在Scala和Spark 2+中,尝试以下操作(假设您的列名称为“ s”): df.select('s).as[String].collect