Apache spark 访问全局查找Apache Spark
我有一个csv文件列表,每个文件都有一组类别名称作为标题列。每一行都是一个具有布尔值(0,1)的用户列表,无论他们是否属于该类别。每个csv文件都没有相同的标题类别集 我想创建一个跨所有文件的复合csv,该文件具有以下输出:Apache spark 访问全局查找Apache Spark,apache-spark,bigdata,Apache Spark,Bigdata,我有一个csv文件列表,每个文件都有一组类别名称作为标题列。每一行都是一个具有布尔值(0,1)的用户列表,无论他们是否属于该类别。每个csv文件都没有相同的标题类别集 我想创建一个跨所有文件的复合csv,该文件具有以下输出: 标头是所有标头的并集 每一行都是唯一的用户,其布尔值对应于类别列 我想要解决这个问题的方法是为每个单元格创建一个用户id和唯一类别id的元组,每个单元格都有一个“1”。然后为每个用户减少所有这些列以获得最终输出 如何创建元组呢?我可以对所有类别进行全局查找吗 示例数据: F
File 1
user_id,cat1,cat2,cat3
21321,,,1,
21322,1,1,1,
21323,1,,,
文件2
user_id,cat4,cat5
21321,1,,,
21323,,1,,
输出
user_id,cat1,cat2,cat3,cat4,cat5
21321,,1,1,,,
21322,1,1,1,,,
21323,1,1,,,,
如果只需要得到结果值,则不需要将此作为两步过程。 一种可能的设计: 1/解析您的csv。您没有提到您的数据是否在分布式FS上,因此我假定它不是。 2/将(K,V)对输入可变并行(利用Spark)映射。 伪代码:
val directory = ..
mutable.ParHashMap map = new mutable.ParHashMap()
while (files[i] != null)
{
val file = directory.spark.textFile("/myfile...")
val cols = file.map(_.split(","))
map.put(col[0], col[i++])
}
然后,您可以通过地图上的迭代器访问(K/V)元组。问题的标题可能具有误导性,因为它传达了某种实现选择,因为不需要全局查找来解决手头的问题 在大数据中,有一个基本原则指导着大多数解决方案:分而治之。在这种情况下,输入CSV文件可以划分为(用户、类别)元组。 任何数量的包含任意数量类别的CSV文件都可以转换为这种简单格式。产生的CSV结果包括上一步的合并、当前类别的总nr提取以及一些数据转换,以获得所需格式 在代码中,此算法如下所示:
import org.apache.spark.SparkContext_
val file1=“”用户id,cat1,cat2,cat3 | 21321,,,,1 | 21322,1,1,1 | 21323,1,,”。拆分(\\\\\)
val file2=“”用户id,cat4,cat5 | 21321,1,| 21323,1”“。拆分(“\\\\”)
val csv1=sparkContext.parallelize(文件1)
val csv2=sparkContext.parallelize(文件2)
导入org.apache.spark.rdd.rdd
def toTuples(csv:RDD[String]):RDD[(String,String)]={
val headerLine=csv.first
val标题=标题线。拆分(“,”)
val data=csv.filter(!=headerLine).map(line=>line.split(“,”))
data.flatMap{elem=>
val merged=elem.zip(标题)
val id=元素头
merged.tail.collect{case(v,cat)if v==“1”=>(id,cat)}
}
}
val data1=toTuples(csv1)
val data2=toTuples(csv2)
val union=data1.union(data2)
val categories=union.map{case(id,cat)=>cat}.distinct.collect.sorted//已排序的类别名称
val categoriesByUser=union.groupByKey.mapValues(v=>v.toSet)
val numericCategoriesByUser=categoriesByUser.mapValues{catSet=>categories.map(cat=>if(catSet(cat))“1”else”“)}
val asCsv=numericCategoriesByUser.collect.map{case(id,cats)=>id+“,”+cats.mkString(“,”)}
结果:
21321,,,1,1,
21322,1,1,1,,
21323,1,,,,1
(生成标题很简单,留给读者作为练习)示例数据将有助于说明您的输入和期望的结果。如果发生冲突,您会怎么做?e、 g.一个csv表示用户id,cat2=0,另一个用户id,cat2=1?。另外,到目前为止您尝试了什么?值的存在优先。到目前为止,我一直试图说服大家,对于MapReduce功能来说,这是一种糟糕的格式。我们控制数据的格式化方式,因此计划对此进行更改。但我很好奇是否有其他人遇到过此类问题。我添加了一个例子,进一步澄清了这个问题。这并不能解决问题。示例令人困惑:我认为(0,1)中可能存在的单元格值,但似乎也存在“21322”值?如果不清楚,我就不好了。该数字是用户id。如果该值存在或不存在,则所有其他值都是1或“”对应的。