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

Java Spark 2.2.0:如何从列表列的数据集中删除特定重复项,java,performance,apache-spark,apache-spark-dataset,Java,Performance,Apache Spark,Apache Spark Dataset,大家早上好,祝大家有一个愉快的一天。我有一个如下的数据集 +-----+------------+ |Text2|Set | +-----+------------+ |seven|[3] | |one |[1, 5, 2, 3]| |six |[5] | |five |[5, 2, 4] | +-----+------------+ 我想做的是从列集合中删除特定的重复项。例如,假设我想同时删除数字3和4 想象一下上面这样的输出。我们可以

大家早上好,祝大家有一个愉快的一天。我有一个如下的数据集

+-----+------------+
|Text2|Set         |
+-----+------------+
|seven|[3]         |
|one  |[1, 5, 2, 3]|
|six  |[5]         |
|five |[5, 2, 4]   |
+-----+------------+
我想做的是从列集合中删除特定的重复项。例如,假设我想同时删除数字3和4

想象一下上面这样的输出。我们可以看到,从列集合的每一行中都删除了3,4

+-----+------------+
|Text2|Set         |
+-----+------------+
|one  |[1, 5, 2]   |
|six  |[5]         |
|five |[5, 2]      |
+-----+------------+
使用Dataset api最有效的方法是什么?因为假设我需要对一个大数据集执行此操作

从我的想法来看,首先映射并执行reduce是实现它的最有效的方法,但我不确定我现在说的是一个愚蠢的解决方案

下面是我的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);
List data=Arrays.asList(
创建(“七”,数组.asList(3)),
创建(“一”,数组.asList(1,5,2,3)),
创建(“六”,数组.asList(5)),
创建(“五”,数组.asList(5,2,4))
);
StructType架构=新StructType(新StructField[]{
新建StructField(“Text2”,DataTypes.StringType,false,Metadata.empty()),
新建StructField(“Set”、DataTypes.createArrayType(DataTypes.IntegerType)、false、Metadata.empty()
});
数据集df=spark.createDataFrame(数据,模式);
df.show(假);

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

假设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]|
  +-----+---------+
Dataset df=sparkSession.createDataFrame(数据,模式);
UDF3 filterFunction=(WrappedArray输入,整数filtVal1,整数filtVal2)->{
List newLst=newarraylist(JavaConversions.asJavaList(input));
newLst.removeIf(x->x==filtVal1 | | x==filtVal2);
返回newLst;
};
register(“filterFunction”,filterFunction,DataTypes.createArrayType(DataTypes.IntegerType));
Dataset filteredDf=df.withColumn(“Set_temp”,functions.callUDF(“filterFunction”,df.col(“Set”),functions.lit(3),functions.lit(4))。drop(“Set”)。withColumn重命名(“Set_temp”,“Set”)。filter(“size(Set_temp)>0”);
filteredDf.show();
+-----+---------+
|文本2 |集|
+-----+---------+
|一|[1,5,2]|
|六|[5]|
|五|[5,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]|
  +-----+---------+
Dataset df=sparkSession.createDataFrame(数据,模式);
UDF3 filterFunction=(WrappedArray输入,整数filtVal1,整数filtVal2)->{
List newLst=newarraylist(JavaConversions.asJavaList(input));
newLst.removeIf(x->x==filtVal1 | | x==filtVal2);
返回newLst;
};
register(“filterFunction”,filterFunction,DataTypes.createArrayType(DataTypes.IntegerType));
Dataset filteredDf=df.withColumn(“Set_temp”,functions.callUDF(“filterFunction”,df.col(“Set”),functions.lit(3),functions.lit(4))。drop(“Set”)。withColumn重命名(“Set_temp”,“Set”)。filter(“size(Set_temp)>0”);
filteredDf.show();
+-----+---------+
|文本2 |集|
+-----+---------+
|一|[1,5,2]|
|六|[5]|
|五|[5,2]|
+-----+---------+


您只需要删除3和4?要删除的元素是否属于列表的一部分?如果是这样,您可以编写一个UDF来检查您传递的数组是否包含列,过滤与要跳过的列表不匹配的列。UDF是否是大数据的有效解决方案?UDF不是低效的,唯一的区别是spark无法为UDF生成优化代码(catalyst Optimizer)逻辑在运行时,它将执行UDF,因为它是。我同意你,但我认为减少功能将更适合我的情况下,你只需要删除3和4?要删除的元素是否属于列表的一部分?如果是这样,您可以编写一个UDF来检查您传递的数组是否包含列,过滤与要跳过的列表不匹配的列。UDF是否是大数据的有效解决方案?UDF不是低效的,唯一的区别是spark无法为UDF生成优化代码(catalyst Optimizer)逻辑在运行时,它将按原样执行UDF。我同意你的观点,但我认为Reduce函数将更适合我的情况。你只需使用
with column(“set”,…)
,而不是创建临时,删除旧名称并将临时名称重命名为旧名称为什么我担心spark 2.2.0是一个更好的解决方案?似乎没有内置函数用于从数组中删除元素,因此使用udf,如果我们有一个,那么我们可以使用它,如果它是scala,那么我们可以消除转换的开销。当修改列时,只需结合使用drop和rename方法,我们就可以直接使用withColumn覆盖数据,性能不会有太大差异,因为它们是元数据操作。我将答案标记为已接受,但我希望您能帮我一个忙,我可以修复代码以将3和4动态传递给udf吗?这是可能的吗?您可以使用
with column(“set”),而不是创建临时,删除旧名称并将临时名称重命名为旧名称为什么我担心spark 2.2.0是一个更好的解决方案?似乎没有内置函数用于从数组中删除元素,因此使用udf,如果我们有一个,那么我们可以使用它,如果它是scala,那么我们可以消除转换的开销。当修改列时,只需结合使用drop和rename方法,我们就可以直接使用withColumn覆盖数据,性能上不会有太大的差异,因为它们是元数据操作。我将答案标记为已接受,但我希望您能帮我一个忙,我可以修复您的代码以动态地将3和4传递给udf这可能吗?