【问题标题】:extract or filter MapType of Spark DataFrame提取或过滤 Spark DataFrame 的 MapType
【发布时间】:2016-04-18 20:23:54
【问题描述】:

我有一个包含各种列的 DataFrame。 一列包含一个 Map[Integer,Integer[]]。 看起来像{ 2345 -> [1,34,2]; 543 -> [12,3,2,5]; 2 -> [3,4]} 现在我需要做的是过滤掉一些键。 我在 Java 中有一组整数 (javaIntSet),我应该用它来过滤

col(x).keySet.isin(javaIntSet)

即。上面的映射应该只包含键 2 和 543 而不是其他两个,过滤后应该看起来像{543 -> [12,3,2,5]; 2 -> [3,4]}。

关于如何使用 Java Column Class 的文档很少。 如何提取 col(x) 以便我可以在 java 中对其进行过滤,然后用过滤后的地图替换单元格数据。或者我忽略了列的任何有用功能。 我可以写一个UDF2<Map<Integer, Integer[]>,Set<Integer>,Map<Integer,Integer[]> 我可以写一个UDF1<String,String>,但我不太确定它如何处理更复杂的参数。

javaIntSet 通常只有十几个,通常少于 100 个值。地图通常也只有少数条目(通常为 0-5 个)。

我必须在 Java 中执行此操作(不幸的是),但我熟悉 Scala。我将自己翻译成 Java 的 Scala 答案已经很有帮助了。

【问题讨论】:

    标签: apache-spark dataframe apache-spark-sql


    【解决方案1】:

    您不需要 UDF。使用一个可能会更干净,但您可以使用DataFrame.explode 轻松做到这一点:

    case class MapTest(id: Int, map: Map[Int,Int])
    val mapDf = Seq(
      MapTest(1, Map((1,3),(2,10),(3,2)) ),
      MapTest(2, Map((1,12),(2,333),(3,543)) )
    ).toDF("id", "map")
    
    mapDf.show
    +---+--------------------+
    | id|                 map|
    +---+--------------------+
    |  1|Map(1 -> 3, 2 -> ...|
    |  2|Map(1 -> 12, 2 ->...|
    +---+--------------------+
    

    然后就可以使用explode了:

    mapDf.explode($"map"){
      case Row(map: Map[Int,Int] @unchecked) => {
        val newMap = map.filter(m => m._1 != 1)   // <-- do filtering here
        Seq(Tuple1(newMap)) 
      }
    }.show
    +---+--------------------+--------------------+
    | id|                 map|                  _1|
    +---+--------------------+--------------------+
    |  1|Map(1 -> 3, 2 -> ...|Map(2 -> 10, 3 -> 2)|
    |  2|Map(1 -> 12, 2 ->...|Map(2 -> 333, 3 -...|
    +---+--------------------+--------------------+
    

    如果你确实想要UDF,它看起来像这样:

    val mapFilter = udf[Map[Int,Int],Map[Int,Int]](map => {
      val newMap = map.filter(m => m._1 != 1)   // <-- do filtering here
      newMap
    })
    
    mapDf.withColumn("newMap", mapFilter($"map")).show
    +---+--------------------+--------------------+
    | id|                 map|              newMap|
    +---+--------------------+--------------------+
    |  1|Map(1 -> 3, 2 -> ...|Map(2 -> 10, 3 -> 2)|
    |  2|Map(1 -> 12, 2 ->...|Map(2 -> 333, 3 -...|
    +---+--------------------+--------------------+
    

    DataFrame.explode 稍微复杂一点,但最终更灵活。例如,您可以将原始行分成两行 - 一行包含已过滤掉元素的地图,另一行包含相反的地图 - 已过滤的元素。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-05-18
      相关资源
      最近更新 更多