Spark 2.2.0:如何从列表列的数据集中删除特定重复项

时间:2017-12-05 12:46:56

标签: java performance apache-spark apache-spark-dataset

GoodMorning给大家,祝你有个美好的一天。我有一个如下的数据集

+-----+------------+
|Text2|Set         |
+-----+------------+
|seven|[3]         |
|one  |[1, 5, 2, 3]|
|six  |[5]         |
|five |[5, 2, 4]   |
+-----+------------+

我想要做的是从Colum集中删除特定的重复项。例如,假设我想要一起删除3号和4号。

想象一下上面的输出。正如我们所看到的,从列Set

的每一行都删除了3,4
+-----+------------+
|Text2|Set         |
+-----+------------+
|one  |[1, 5, 2]   |
|six  |[5]         |
|five |[5, 2]      |
+-----+------------+

使用Dataset api执行此操作的最有效方法是什么?因为我们假设我需要对大数据进行此操作

从我的想法是先将地图和执行减少作为实现它的最有效方式,但我不确定我现在所说的是一个愚蠢的解决方案。

这是我的Java代码示例

 List<Row> data = Arrays.asList(
                RowFactory.create("seven", Arrays.asList(3)),
                RowFactory.create("one", Arrays.asList(1, 5, 2, 3)),
                RowFactory.create("six", Arrays.asList(5)),
                RowFactory.create("five", Arrays.asList(5, 2, 4))
        );

        StructType schema = new StructType(new StructField[]{
                new StructField("Text2", DataTypes.StringType, false, Metadata.empty()),
                new StructField("Set", DataTypes.createArrayType(DataTypes.IntegerType), false, Metadata.empty())
        });

        Dataset<Row> df = spark.createDataFrame(data, schema);
        df.show(false);

如果有人能根据我的问题给我一个解决方案,我将不胜感激

1 个答案:

答案 0 :(得分:2)

让我们说 df 是代码过滤器下方的初始数据框,与您期望的方式相同。

Dataset<Row> df = sparkSession.createDataFrame(data, schema);

    UDF3<WrappedArray<Integer>,Integer,Integer,List<Integer>> filterFunction =  (WrappedArray<Integer> input, Integer filtVal1,Integer filtVal2) -> {
        List<Integer> newLst= new ArrayList<>(JavaConversions.asJavaList(input));
        newLst.removeIf(x -> x==filtVal1 || x==filtVal2);
        return newLst;
    };

    sparkSession.udf().register("filterFunction", filterFunction, DataTypes.createArrayType(DataTypes.IntegerType));

    Dataset<Row> filteredDf= df.withColumn("Set_temp", functions.callUDF("filterFunction", df.col("Set"),functions.lit(3),functions.lit(4))).drop("Set").withColumnRenamed("Set_temp", "Set").filter("size(Set_temp)>0");

    filteredDf.show();

  +-----+---------+
  |Text2|      Set|
   +-----+---------+
  |  one|[1, 5, 2]|
  |  six|      [5]|
  | five|   [5, 2]|
  +-----+---------+