当前位置: 首页 > 知识库问答 >
问题:

使用scala的布尔运算在火花数据帧中折叠列

陶睿
2023-03-14

我们如何使用scala使用OR操作将布尔列折叠成一行?

第1部分:

A  true
A  false
B  false
B  false
C  true
B  false
A  true
C  true

期望输出


B  false
A  true
C  true

我能想到的一个解决方案是按第一列条目对它们进行分组,filter true

这个解决方案相当混乱。此外,不知道这是否适用于所有边缘情况。有什么聪明的方法可以做到这一点吗?



编辑:给定的答案适用于上述给定的场景,但不适用于此场景。有什么方法可以实现所需的输出?

第2部分:

A  true    "Apple"
A  false   ""
B  false   ""
B  false   ""
C  true    "Cat"
C  true    "Cotton"
C  false   ""

期望输出


B  false []
A  true  ["Apple"]
C  true  ["Cat","Cotton"]

我试图通过col1和col2分组,然后用collect_set折叠col3来实现这一点,然后

  1. 按第一列分组
  2. 将第二列收集为布尔值集
  3. 检查是否只有一个true如果是,则OR表达式的计算结果将始终为true

但这会导致col3_集合的丢失。

共有2个答案

党源
2023-03-14

试试这个:

  1. col1上的分组

将步骤2中收集的布尔值集传递给UDF,UDF将对所有元素执行一个简单的递归操作

scala> val df = List(
     | ("A",  true),
     | ("A",  false),
     | ("B",  false),
     | ("B",  false),
     | ("C",  true),
     | ("B",  false),
     | ("A",  true),
     | ("C",  true)
     | ).toDF("col1","col2")
df: org.apache.spark.sql.DataFrame = [col1: string, col2: boolean]

scala> df.show
+----+-----+
|col1| col2|
+----+-----+
|   A| true|
|   A|false|
|   B|false|
|   B|false|
|   C| true|
|   B|false|
|   A| true|
|   C| true|
+----+-----+


scala> val aggOr = udf((a:Seq[Boolean])=>{a.reduceLeft(_||_)})
aggOr: org.apache.spark.sql.expressions.UserDefinedFunction = UserDefinedFunction(<function1>,BooleanType,Some(List(ArrayType(BooleanType,false))))

scala> df.groupBy("col1").agg(aggOr(collect_set("col2")).as("col2Or")).show
+----+------+
|col1|col2Or|
+----+------+
|   B| false|
|   C|  true|
|   A|  true|
+----+------+
单于煌
2023-03-14
  1. 按第1列分组
  2. 收集第二列作为布尔集合
  3. 收集第3列作为字符串集
  4. 检查是否有一个true如果是,那么OR表达式将始终求值为true。
  5. 删除空字符串"col3_set
import org.apache.spark.sql.functions._

object GroupByAgg {

  def main(args: Array[String]): Unit = {

    val spark = Constant.getSparkSess

    import spark.implicits._

    val df = List(("A", true,"Apple"), ("A", false,""),
      ("B", false,""),
      ("B", false,""),
      ("C", true,"Cat"),
      ("C", true,"Cotton"),
      ("C", true,"")).toDF("Col1", "Col2","Col3")

    //Group by 1st column
    df.groupBy("Col1")
      // Collect unique values
      .agg(collect_set("Col2").as("Col2_set"),collect_set("Col3").as("Col3_set"))
      //check if the array contains single true
      .withColumn("OutputCol2", when(array_contains(col("Col2_set"), true), true)
        .otherwise(false))
    .withColumn("OutputCol3",array_remove(col("Col3_set"),lit("")))
//.withColumn("OutputCol3",expr("filter(Col3_set, x -> x != '')"))
      .drop("Col2_set")
      .drop("Col3_set")
      .show()
  }

}

输出:

+----+----------+-------------+
|Col1|OutputCol2|   OutputCol3|
+----+----------+-------------+
|   B|     false|           []|
|   C|      true|[Cat, Cotton]|
|   A|      true|      [Apple]|
+----+----------+-------------+
 类似资料:
  • 我试图找出我的DataFrame列中是否存在特定的列,但我有一些问题。 我所做的:使用布尔运算“notin”(我尝试了any()、all()、“in”)来查找特定的列标题,但它似乎工作不正常! 假设我的DataFrame列标题是: 我想看看是否所有的‘M1’、‘M2’、…'M20'和TM1'在那里。如果一个或多个代码丢失,则该代码将不起作用。 所以我说: 现在,假设df具有所有询问列标题,if语句

  • 如何在火花scala数据帧(非文本)api中访问geomesas UDF?即如何转换 如何使sql UDF在scala数据帧DSL中的文本spark sql API中可用?即如何启用而不是此表达式 类似于 如何注册Geomesa UDF,使其不仅适用于sql文本模式<代码>SQLTypes。init(spark.sqlContext)fromhttps://github.com/locationt

  • 我想将包含字符串记录的RDD转换为Spark数据帧,如下所示。 模式行不在同一个中,而是在另一个变量中: 所以现在我的问题是,我如何使用上面两个,在Spark中创建一个数据帧?我使用的是Spark 2.2版。 我确实搜索并看到了一篇帖子:我可以使用spack-csv将表示为字符串的CSV读取到Apache Spark中吗?然而,这并不是我所需要的,我也无法找到一种方法来修改这段代码以在我的情况下工

  • 我想过滤掉具有“c2”列前3个字符的记录,无论是“MSL”还是“HCP”。 所以输出应该如下所示。 有谁能帮忙吗? 我知道df。过滤器($c2.rlike(“MSL”))--用于选择记录,但如何排除记录? 版本:Spark 1.6.2 Scala:2.10

  • 当我尝试将数据帧写入Hive Parket分区表时 它将在HDFS中创建大量块,每个块只有少量数据。 我了解它是如何进行的,因为每个 spark 子任务将创建一个块,然后将数据写入其中。 我也理解,块数会提高Hadoop的性能,但达到阈值后也会降低性能。 如果我想自动设置数字分区,有人有一个好主意吗?

  • 并将其应用于数据表的一列--这是我希望这样做的: 我还没有找到任何简单的方法,正在努力找出如何做到这一点。一定有一个更简单的方法,比将数据rame转换为和RDD,然后从RDD中选择行来获得正确的字段,并将函数映射到所有的值,是吗?创建一个SQL表,然后用一个sparkSQL UDF来完成这个任务,这更简洁吗?