Apache spark Spark:如何创建一个映射函数,该函数可以获取一批数据行,对每一行进行一些处理,并输出一批修改的行

Apache spark Spark:如何创建一个映射函数,该函数可以获取一批数据行,对每一行进行一些处理,并输出一批修改的行,apache-spark,Apache Spark,我有一个以下格式的数据文件 id 0 1 2 3 4 5 6 7 我需要对此文件执行以下操作: 1) 将数据分成4个存储桶,并在每行上标记一个存储桶。该文件应具有以下格式: id Bucket Num 0 0 1 0 2 0 3 0 4 1 5 1 6 1 7 1 我使用了以下Scala代码来实现这一点: val fileRDD = sc.textFile(inputFile).zipWithIndex()

我有一个以下格式的数据文件

id
 0
 1
 2
 3
 4
 5
 6
 7
我需要对此文件执行以下操作:

1) 将数据分成4个存储桶,并在每行上标记一个存储桶。该文件应具有以下格式:

id Bucket Num
 0  0
 1  0
 2  0
 3  0
 4  1
 5  1
 6  1
 7  1
我使用了以下Scala代码来实现这一点:

val fileRDD = sc.textFile(inputFile).zipWithIndex()
                  .filter(_._2 > 0)
                  .map{case (k,v) => ((v/4).toString() + delimiter + k)}  
                  .map{_.split(delimiter)}
                  .map(s=>Row.fromSeq(s.toSeq))
2) 然后,我需要读取具有特定bucket编号的文件的所有行,运行一些业务逻辑并创建如下输出

id Bucket Num  Emp Num
 0  0            1
 1  0            4
 2  0            2
 3  0            3
 4  1            3
 5  1            2
 6  1            4
 7  1            1
在上面的输出中,函数需要读入特定bucket#的所有文件行,执行一些业务逻辑,并在数据的每一行上标记一个Emp Num


我想不出执行步骤2的方法。有人能帮我吗?

因为您的源文件中可能有多个列,所以我对测试数据进行了一些扩展

val sc:SparkContext=。。。
val电影=sc.parallelize(序号(
(0,《肖申克的救赎》,1994年),
(1,《教父》,1972年),
(2,“教父:第二部分”,1974年),
(3,《黑暗骑士》,2008年),
(4,“辛德勒名单”,1993年),
(5,“12个愤怒的人”,1957年),
(6,“低俗小说”,1994年),
(7,“指环王:国王的回归”,2003年)
))
val results=movies.map{case(id,movie,year)=>
(id/4,(id,电影,年份))//您可以选择自己的方法来确定存储桶编号
}.groupByKey().flatMap{大小写(bucket,记录)=>
records.map{案例(id、电影、年份)=>
(id,bucket,movie,year,year+bucket+1)//您应该放置自己的自定义逻辑,而不是'year+bucket+1'
}
}
results.collect()foreach println
输出:

(0,0,The Shawshank Redemption,1994,1995)
(1,0,The Godfather,1972,1973)
(2,0,The Godfather: Part II,1974,1975)
(3,0,The Dark Knight,2008,2009)
(4,1,Schindler's List,1993,1995)
(5,1,12 Angry Men,1957,1959)
(6,1,Pulp Fiction,1994,1996)
(7,1,The Lord of the Rings: The Return of the King,2003,2005)

如果您在理解或使用此解决方案时遇到任何问题,请告诉我。

因为您的源文件中可能有多个列,所以我对测试数据进行了一些扩展

val sc:SparkContext=。。。
val电影=sc.parallelize(序号(
(0,《肖申克的救赎》,1994年),
(1,《教父》,1972年),
(2,“教父:第二部分”,1974年),
(3,《黑暗骑士》,2008年),
(4,“辛德勒名单”,1993年),
(5,“12个愤怒的人”,1957年),
(6,“低俗小说”,1994年),
(7,“指环王:国王的回归”,2003年)
))
val results=movies.map{case(id,movie,year)=>
(id/4,(id,电影,年份))//您可以选择自己的方法来确定存储桶编号
}.groupByKey().flatMap{大小写(bucket,记录)=>
records.map{案例(id、电影、年份)=>
(id,bucket,movie,year,year+bucket+1)//您应该放置自己的自定义逻辑,而不是'year+bucket+1'
}
}
results.collect()foreach println
输出:

(0,0,The Shawshank Redemption,1994,1995)
(1,0,The Godfather,1972,1973)
(2,0,The Godfather: Part II,1974,1975)
(3,0,The Dark Knight,2008,2009)
(4,1,Schindler's List,1993,1995)
(5,1,12 Angry Men,1957,1959)
(6,1,Pulp Fiction,1994,1996)
(7,1,The Lord of the Rings: The Return of the King,2003,2005)

如果您在理解或使用此解决方案时遇到任何问题,请告诉我。

我将在
bucketNum
值上使用
groupBy
方法开始第二步。然后你会有4个分区的RDD,比如(bucketNum,CompactBuffer(record_0,record_1,…,record_n)。然后你会用你的函数映射到CompactBuffer上(对于不同的bucketNum,它甚至可能是不同的函数)。下面是困难的部分(但绝对可能):从已处理的4个分区返回到完整的RDD。您可以使用
flatMap
方法将每个分区的内容转换为列表,这将“强制”Spark从这四个分区中创建原始的N个分区。如果你能提供一些虚假/测试数据,我会编写一个完整的解决方案,并将其作为答案发布在这里。@Pawel我用一些数据修改了上面的示例。希望这能帮助你编写代码。我将使用
groupBy
方法对
bucketNum
值开始第二步s、 然后你会有4个分区的RDD,比如(bucketNum,CompactBuffer(record_0,record_1,…,record_n)。然后你会用你的函数映射到CompactBuffer上(对于不同的bucketNum,它甚至可能是不同的函数)。下面是困难的部分(但绝对可能):从已处理的4个分区返回到完整的RDD。您可以使用
flatMap
方法将每个分区的内容转换为列表,这将“强制”Spark从这四个分区中创建原始的N个分区。如果您能提供一些虚假/测试数据,我会编写一个完整的解决方案,并将其作为答案发布在这里。@Pawel我用一些数据修改了上面的示例。希望这能帮助您编写代码。