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这可能吗?