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


86

我想将数据框的字符串列转换为列表。我可以从DataframeAPI中找到RDD,因此我尝试先将其转换回RDD,然后再将toArray功能应用于RDD。在这种情况下,长度和SQL都可以正常工作。但是,我从RDD得到的结果在每个像这样的元素周围都有方括号[A00001]。我想知道是否有适当的方法可以将列转换为列表,也可以删除方括号。

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


Answers:


116

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

dataFrame.select("YOUR_COLUMN_NAME").rdd.map(r => r(0)).collect()

没有映射,您只会得到一个Row对象,其中包含数据库中的每一列。

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

PS由于自动转换,您可以跳过该.rdd部分。


3
出于某种奇怪的原因,它以相反的方式工作(Spark 2.1.0)collect().map(r => r(0))-此命令有什么缺点吗?
布尔恩'17

可能会比较慢-您的解决方案首先收集驱动程序上的所有数据,然后才仅使用单个驱动程序的处理能力就在驱动程序上进行映射(没有执行者的帮助)。
Niemand

72

使用Spark 2.x和Scala 2.11

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

所有方法的通用代码段

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")

方法1

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

现在会发生什么?我们正在使用收集数据到Drivercollect()并从每个记录中选择元素零。

这可能不是一个很好的方法,让我们用下一种方法进行改进。


方法2

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

效果如何?我们在工作人员之间分配了地图转换负载,而不是由单个驱动程序分配。

我知道rdd.map(r => r(0))你似乎并不优雅。因此,让我们在下一种方法中解决它。


方法3

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

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

结论

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

Databricks笔记本


24

我知道给定和要求的答案都是针对Scala的,因此,我只是提供一些Python代码片段,以防PySpark用户感到好奇。语法类似于给定的答案,但是要正确弹出列表,我实际上必须在映射函数中第二次引用列名,并且不需要select语句。

即一个DataFrame,其中包含一个名为“ Raw”的列

为了将“原始”中的每个行值组合成一个列表,其中每个条目都是“原始”中的行值,我只需使用:

MyDataFrame.rdd.map(lambda x: x.Raw).collect()

4
这给出了行对象的列表。如果您想要一个值列表怎么办?
ThatDataGuy

这给出了值列表。
艾比·索布

感谢您分享!这对我很有用,只是想知道是否有一种方法可以加快速度,它运行得很慢
Mojgan Mazouchi

5

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


3
sqlContext.sql(" select filename from tempTable").rdd.map(r => r(0)).collect.toList.foreach(out_streamfn.println) //remove brackets

它完美地工作


1
List<String> whatever_list = df.toJavaRDD().map(new Function<Row, String>() {
    public String call(Row row) {
        return row.getAs("column_name").toString();
    }
}).collect();

logger.info(String.format("list is %s",whatever_list)); //verification

由于没有人用java(Real Programming Language)提供任何解决方案,待会儿再感谢我


0
from pyspark.sql.functions import col

df.select(col("column_name")).collect()

这里的collect是将其转换为列表的函数。当心使用庞大数据集上的列表。它将降低性能。检查数据很好。



0

更新的解决方案为您提供了一个列表:

dataFrame.select("YOUR_COLUMN_NAME").map(r => r.getString(0)).collect.toList
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.