我对Spark在概念上理解得很好,但我仍然在导航表达式的特定语法选项.我使用的是带有Java 17的Spark 3.3.0.

我有一个表,其列为foo,其值不应高于30.我想添加一个比例为foo30的列,即foo的值归一化为0.0 <= proportion <= 1.0,foo的分界值为30.最后,foo是一个DECIMAL类型,在Java中用BigDecimal表示.

在Java中,我可能会这样计算:

BigDecimal maxVal = new BigDecimal(30); 
BigDecimal proportion = foo.max(maxVal).divide(maxVal);

(或者我可以先除以maxVal,然后取结果的最大值和1.0,尽管上面的第一种方法在语义上可能更高效、更直接.)

在《星火》里,我该怎么做才是最好的?以下几条似乎很管用,让我走到了最远的地方:

BigDecimal maxVal = new BigDecimal(30);
df = df.withColumn("proportion", col("foo").divide(maxVal));

max()的那部分怎么样,这样我就可以把它的值砍到30了?我能随手找到的唯一"max"函数是Spark SQL MAX()聚合函数.

推荐答案

虽然minmax是在一组行上工作的聚合函数,但是函数leastgreatest可以比较行内的值或与常量值进行比较.

import static org.apache.spark.sql.functions.*;

Dataset<Row> df = ...
BigDecimal maxVal=new BigDecimal(30);
df.withColumn("proportion", greatest(col("value"), lit(maxVal)).divide(maxVal)).show();

输出:

+-----+----------+
|value|proportion|
+-----+----------+
|    1|  1.000000|
|   10|  1.000000|
|   20|  1.000000|
|   30|  1.000000|
|   31|  1.033333|
|   40|  1.333333|
+-----+----------+

如果这些值的上限应该是maxValue,则应该使用least而不是greatest(这相当于在非Spark代码中使用BigDecimal.min):

df.withColumn("proportion", least(col("value"), lit(maxVal)).divide(maxVal)).show();

现在输出:

+-----+----------+
|value|proportion|
+-----+----------+
|    1|  0.033333|
|   10|  0.333333|
|   20|  0.666667|
|   30|  1.000000|
|   31|  1.000000|
|   40|  1.000000|
+-----+----------+

Java相关问答推荐

我可以在regex中的字符类中放置断言吗?

Android视图覆盖不阻止点击它后面的控件

int Array Stream System. out. print方法在打印Java8时在末尾添加% sign

空手道比赛条件

Java Stream,需要更新列表对象列表

SQlite for Android无法使用json_group_array/json_object

Apache POI:使用反射获取zoom 级别

错误:在Liferay7.4中找不到符号导入com.liferay.portal.kernel.uuid.PortalUUID;";

SpringBoot+Java 17@Valid未验证POJO

我不能再在Android Studio Hedgehog上用Java语言创建新项目了吗?

使用Spring和ActiveMQ的侦听器方法引发属性名称不能重复为空警告

为什么当我创建Robot对象时,JavaFX引发IlLegalStateException异常?

Java中不兼容的泛型类型

有谁能帮我修一下这个吗?使输出变得更加整洁

如何获得凌空cookies ,并设置它在下一个请求- android

Java 21中泛型的不兼容更改

如何设置默认序列生成器分配大小

如何用Micrometer&;斯普肯

在JSON上获取反斜杠

Xml Reader 将 BMP 外部的字符解析为代理项对,这会导致无效的 xml