【问题标题】:Extract column values of Dataframe as List in Apache Spark在 Apache Spark 中将 Dataframe 的列值提取为 List
【发布时间】:2015-11-07 03:41:42
【问题描述】:

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

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

【问题讨论】:

标签: scala apache-spark apache-spark-sql


【解决方案1】:

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

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

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

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

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

【讨论】:

  • 由于某种奇怪的原因,它反过来工作(Spark 2.1.0)collect().map(r => r(0)) - 这个命令有什么缺点吗?
  • 可能更慢 - 您的解决方案首先收集驱动程序上的所有数据,然后在驱动程序上进行映射(无需执行器辅助),仅使用单个驱动程序的处理能力。跨度>
【解决方案2】:

我知道给出和要求的答案是假定为 Scala 的,所以我只是提供一点 Python 代码 sn-p 以防 PySpark 用户好奇。语法类似于给定的答案,但要正确弹出列表,我实际上必须在映射函数中再次引用列名,并且不需要 select 语句。

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

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

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

【讨论】:

  • 这给出了 Row 对象的列表。如果你想要一个值列表怎么办?
  • 这给出了一个值列表。
  • 感谢分享!这对我很有用,只是想知道是否有办法加快速度,它运行速度很慢
【解决方案3】:

使用 Spark 2.x 和 Scala 2.11

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

所有方法的通用代码sn-ps

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)

现在会发生什么?我们正在使用 collect() 向 Driver 收集数据,并从每条记录中挑选元素零。

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


方法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。查看map,由于DataFrame 中的编码器问题,它不会接受r => r(0)(或_(0))作为以前的方法。所以最终使用r => r.getString(0),它将在下一版本的 Spark 中解决。

结论

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

Databricks notebook

【讨论】:

  • 对于在作业集群上运行的数据块作业,我尝试了多种方法,但没有填充列表。它在本地工作,但不在集群作业中。方法1解决了我的问题。赞赏。
【解决方案4】:

在 Scala 和 Spark 2+ 中,试试这个(假设你的列名是“s”):

df.select('s').as[String].collect

【讨论】:

    【解决方案5】:
    sqlContext.sql(" select filename from tempTable").rdd.map(r => r(0)).collect.toList.foreach(out_streamfn.println) //remove brackets
    

    效果很好

    【讨论】:

      【解决方案6】:
      from pyspark.sql.functions import col
      
      df.select(col("column_name")).collect()
      

      这里 collect 是函数,这些函数又将其转换为列表。 小心在庞大的数据集上使用列表。它会降低性能。 查资料就好了。

      【讨论】:

        【解决方案7】:

        这是java答案。

        df.select("id").collectAsList();
        

        【讨论】:

          【解决方案8】:
          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)中给出任何解决方案 以后可以感谢我

          【讨论】:

            【解决方案9】:

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

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

            【讨论】:

              【解决方案10】:

              下面是 Python-

              df.select("col_name").rdd.flatMap(lambda x: x).collect()
              

              【讨论】:

              • 其他答案(如stackoverflow.com/a/59841515/6807769)类似
              • @VincentDoba - 查询总是会有类似的答案。它不一样,在这个线程中没有一个答案在 python 中使用 flatMap。投反对票而不是帮助人们很容易。无论如何。
              猜你喜欢
              • 2017-02-26
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-10-05
              相关资源
              最近更新 更多