[英]Using the Apache Spark RDD map method (Java API) to produce a non-columnar result
请注意:我相信我在这里尝试使用 RDD map
方法是正确的,但如果有另一种方法来完成我正在寻找的东西,我会全力以赴!
Spark 2.4.x 的全新版本,使用Java (不是Scala)API。
我正试图围绕 RDD map(...)
方法,特别是在Datasets
上,而不仅限于 RDD。 官方文档中使用它的典型示例是:
public class GetLength implements Function<String, Integer> {
public Integer call(String s) { return s.length(); }
}
JavaRDD<String> lines = sc.textFile("data.txt");
JavaRDD<Integer> lineLengths = lines.map(new GetLength());
因此,在这种情况下,似乎在创建 RDD lines
之后,它有一个列(我不确定其名称),其中每列值是文件的不同行,并且 RDD 中的每一行也代表文件的不同行。 意思是, lines
是一个nx1
矩阵,其中n
是文件中的行数/行数。
似乎当GetLength
function 被执行时,它被输入每一行的唯一列作为输入字符串,并返回一个 integer 表示该字符串的行长度作为不同数据集中的新列值,这也是nx1
(只保存行长度信息而不是实际的行/字符串)。
好的,所以我得到了那个简单的例子。 但是,如果我们有nxm
数据集,意思是很多行和很多列,并且我们想编写将它们转换为其他nxm
数据集的函数怎么办?
例如,假设我有以下“输入”数据集:
+-------------------------+
| price | color | fizz |
+-------------------------+
| 2.99 | red | hallo |
| 13.94 | blue | yahtzee |
| 7.19 | red | trueth |
...
| 4.15 | green | whatevs |
+-------------------------+
其中price
是数字/浮点类型,而color
和fizz
都是字符串。 所以这里我们有一个nx3
形状的数据集; n
行,每行总是 3 列。
我将如何编写一个 map function 也返回一个nx3
数据集,具有相同的列/列名称/模式,但不同的值(基于函数)?
例如,假设我想要一个具有相同架构的新nx3
数据集,但是如果行的color
值等于字符串"red"
,那么将2.0
添加到price
列?
因此,使用上面的任意数据集,来自此 map function 的新数据集将如下所示:
+-------------------------+
| price | color | fizz |
+-------------------------+
| 4.99 | red | hallo | <== added 2.0 to price since color == "red"
| 13.94 | blue | yahtzee |
| 9.19 | red | trueth | <== added 2.0 to price since color == "red"
...
| 4.15 | green | whatevs |
+-------------------------+
我很想做类似的事情:
public class UpdatedPriceForRedColors implements Function2<String, Double, Double> {
public Double call(String color, Double currentPrice) {
if ("red".equals(color) {
return currentPrice + 2.0;
} else {
return currentPrice;
}
}
}
JavaRDD<Double> updatedPrices = myDS.map(new UpdatedPriceForRedColors());
但是,这里有几个问题:
updatedPrices
现在只是一个nx1
数据集,由myDS
中每一行的正确计算价格组成,而我想要具有相同price/color/fizz
的东西,看起来像上面的第二个任意数据集UpdatedPriceForRedColors
如何知道它的第一个字符串参数是color
列,而不是fizz
列?Function5
or Function6
(it's hard to discern what is available to the Java API and what is exclusive to the Scala API). 这意味着我只能编写包含 5 或 6 个 arguments 的函数,而我可能有包含 10 多列的数据集,我可能非常需要将这些列值中的大部分“注入”到 function 中,这样我就可以计算返回值新数据集的值。 在这种情况下,我有哪些选择?首先,RDD 总是有一个column ,因为 RDD 没有模式信息,因此您与RDD<T>
中的T
类型相关联。
选项 1是使用Function<String,String>
解析RDD<String>
String
的字符串,执行操作字符串中的内部元素的逻辑,并返回更新的字符串。
如果您希望您的RDD
有一些架构信息,您可以使用RDD<Row>
,它可以让您访问Row
中的单独元素(选项 2) 。
import org.apache.spark.sql.Row
JavaRDD<Row> rddRow = rddString.map(new Function<String, Row>() {
@Override
public Row call(String line) throws Exception {
String[] parts = line.split("\\t");//tab separated values
Row row = RowFactory.create(parts[0], parts[1], parts[2]);
return row;
}
});
现在您可以 map 行:
RDD<Row> updatedRdd = rddRow.map(new Function<Row, Row>() {
@Override
public Row call(Row row) throws Exception {
Float price = row.get(0);
String color = row.get(1);
//Your logic here
Row row = RowFactory.create(/* three elements here, or whatever*/);
return row;
}
});
如果您进一步使用 go,则可以使用真正的数据集(如此处所述)并利用数据帧/数据集 API (选项 3) 。
import org.apache.spark.sql.Row
import org.apache.spark.sql.types.DataTypes;
import org.apache.spark.sql.types.StructField;
import org.apache.spark.sql.types.StructType;
StructType schema = DataTypes.createStructType(
new StructField[]{
DataTypes.createStructField("price", FloatType, false),
DataTypes.createStructField("color", StringType, false),
DataTypes.createStructField("fizz", StringType, false)
});
JavaRDD<Row> rddRow = rddString.map(new Function<String, Row>() {
@Override
public Row call(String line) throws Exception {
String[] parts = line.split("\\t");//tab separated values
Row row = RowFactory.create(parts[0], parts[1], parts[2]);
return row;
}
});
DataFrame df = sqlContext.createDataFrame(rowRDD, schema);
拥有 dataframe 现在可以让您使用以下内容:
DataFrame df2 = df.withColumn("price",
when(col("color").equals("red"), col("price").add(2f))
.otherwise(col("price")));
免责声明:我没有检查过 java 语法和 API,因为我已经习惯了 scala。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.