我有一个数据集,其中包含格式的行(制表符分隔):
Title<\t>Text
现在,对于Text
中的每个字词,我想创建一个(Word,Title)
对。
例如:
ABC Hello World
给了我
(Hello, ABC)
(World, ABC)
使用Scala,我写了以下内容:
val file = sc.textFile("s3n://file.txt")
val title = file.map(line => line.split("\t")(0))
val wordtitle = file.map(line => (line.split("\t")(1).split(" ").map(word => (word, line.split("\t")(0)))))
但这给了我以下输出:
[Lscala.Tuple2;@2204b589
[Lscala.Tuple2;@632a46d1
[Lscala.Tuple2;@6c8f7633
[Lscala.Tuple2;@3e9945f3
[Lscala.Tuple2;@40bf74a0
[Lscala.Tuple2;@5981d595
[Lscala.Tuple2;@5aed571b
[Lscala.Tuple2;@13f1dc40
[Lscala.Tuple2;@6bb2f7fa
[Lscala.Tuple2;@32b67553
[Lscala.Tuple2;@68d0b627
[Lscala.Tuple2;@8493285
我该如何解决这个问题?
进一步阅读
我想要实现的是计算特定Words
的{{1}}中Text
的数量。
我写的后续代码是:
Title
但它不起作用。请随时提供您的意见。谢谢!
答案 0 :(得分:7)
所以......在Spark中你使用名为RDD的分布式数据结构。它们提供类似于scala的集合类型的功能。
val fileRdd = sc.textFile("s3n://file.txt")
// RDD[ String ]
val splitRdd = fileRdd.map( line => line.split("\t") )
// RDD[ Array[ String ]
val yourRdd = splitRdd.flatMap( arr => {
val title = arr( 0 )
val text = arr( 1 )
val words = text.split( " " )
words.map( word => ( word, title ) )
} )
// RDD[ ( String, String ) ]
// Now, if you want to print this...
yourRdd.foreach( { case ( word, title ) => println( s"{ $word, $title }" ) } )
// if you want to count ( this count is for non-unique words),
val countRdd = yourRdd
.groupBy( { case ( word, title ) => title } ) // group by title
.map( { case ( title, iter ) => ( title, iter.size ) } ) // count for every title
答案 1 :(得分:2)
使用较新的数据框API 可解决此问题。首先使用“\ t”作为分隔符读取数据:
val df = spark.read
.option("delimiter", "\t")
.option("header", false)
.csv("s3n://file.txt")
.toDF("title", "text")
然后,split
空格text
列和explode
每行一个字。
val df2 = df.select($"title", explode(split($"text", " ")).as("words"))
最后,在title
列上进行分组,并计算每个字词的数量。
val countDf = df2.groupBy($"title").agg(count($"words"))
答案 2 :(得分:0)
具有DataFrame API的另一个版本
// read into DataFrame
val viewsDF=spark.read.text("s3n://file.txt")
// Split
val splitedViewsDF = viewsDF.withColumn("col1", split($"value", "\\t").getItem(0)).withColumn("col2", split($"value", "\\s+").getItem(1)).drop($"value"))
scala> val viewsDF=spark.read.text("spark-labs/data/wiki-pageviews.txt")
viewsDF: org.apache.spark.sql.DataFrame = [value: string]
scala> viewsDF.printSchema
root
|-- value: string (nullable = true)
scala> viewsDF.limit(5).show
+------------------+
| value|
+------------------+
| aa Main_Page 3 0|
| aa Main_page 1 0|
| aa User:Savh 1 0|
| aa Wikipedia 1 0|
|aa.b User:Savh 1 0|
+------------------+
scala> val splitedViewsDF = viewsDF.withColumn("col1", split($"value", "\\s+").getItem(0)).withColumn("col2", split($"value", "\\s+").getItem(1)).withColumn("col3", split($"value", "\\s+").getItem(2)).drop($"value")
splitedViewsDF: org.apache.spark.sql.DataFrame = [col1: string, col2: string ... 1 more field]
scala>
scala> splitedViewsDF.printSchema
root
|-- col1: string (nullable = true)
|-- col2: string (nullable = true)
|-- col3: string (nullable = true)
scala> splitedViewsDF.limit(5).show
+----+---------+----+
|col1| col2|col3|
+----+---------+----+
| aa|Main_Page| 3|
| aa|Main_page| 1|
| aa|User:Savh| 1|
| aa|Wikipedia| 1|
|aa.b|User:Savh| 1|
+----+---------+----+
scala>
答案 3 :(得分:0)
上面证明的答案还不够好。
.map( line => line.split("\t") )
可能导致:
org.apache.spark.SparkException:由于阶段失败而导致作业中止:阶段18.0中的任务0失败4次,最近一次失败:阶段18.0中的任务0.3丢失(TID 1485,ip-172-31-113-181 .us-west-2.compute.internal,执行程序10):java.lang.RuntimeException:编码时出错:java.lang.ArrayIndexOutOfBoundsException:14
如果最后一列为空。 最好的结果在这里解释- Split 1 column into 3 columns in spark scala