我有.tsv
个文件pageviews_by_second
,其中包含timestamp
site
和requests
字段:
"timestamp" "site" "requests"
"2015-03-16T00:09:55" "mobile" 1595
"2015-03-16T00:10:39" "mobile" 1544
"2015-03-16T00:19:39" "desktop" 2460
我希望第一行消失,因为它导致我必须对数据执行的操作出错。
我尝试通过以下方式进行:
1.在分割之前过滤RDD
val RDD1 = sc.textFile("pageviews_by_second")
val top_row = RDD1.first()
//returns: top_row: String = "timestamp" "site" "requests"
val RDD2 = RDD1.filter(x => x!= top_row)
RDD2.first()
//returns: "2015-03-16T00:09:55" "mobile" 1595
2.分割后过滤RDD
val RDD1 = sc.textFile("pageviews_by_second").map(_.split("\t")
RDD1.first() //returns res0: Array[String] = Array("timestamp, 'site", "requests")
val top_row = RDD1.first()
val RDD2 = RDD1.filter(x => x!= top_row)
RDD2.first() //returns: res1: Array[String] = Array("timestamp", "site" ,"requests")
val RDD2 = RDD1.filter(x => x(0)!="timestamp" && x(1)!="site" && x(2)!="requests")
RDD2.first() //returns: res1: Array[String] = Array("timestamp", "site" ,"requests")
3.使用' case class'转换为DataFrame。并过滤它
case class Wiki(timestamp: String, site: String, requests: String)
val DF = sc.textFile("pageviews_by_second").map(_.split("\t")).map(w => Wiki(w(0), w(1), w(2))).toDF()
val top_row = DF.first()
//returns: top_row: org.apache.spark.sql.Row = ["timestamp","site","requests"]
DF.filter(_ => _ != top_row)
//returns: error: missing parameter type
val DF2 = DF.filter(_ => _ != top_row2)
为什么只有第一种方法能够过滤掉第一行,而另外两种方法不能?在方法3中,为什么我会得到错误以及如何纠正错误?
答案 0 :(得分:2)
首先,您需要了解在删除顶行时要比较的数据类型。
比较两个字符串将在方法1中产生true或false。因此它会过滤掉顶行
在方法2中,您正在比较2个Arrays。使用deep
数组方法对scala中的数组进行更深入的比较
Method2
val RDD1 = sc.textFile("D:\\trial.txt").map(_.split("\t"))
val top_row = RDD1.first()
val RDD2 = RDD1.filter(x => x.deep!= top_row.deep)
RDD2.first().foreach(println(_))
在方法3中,您要比较数据帧的两行对象。最好将行转换为toSeq
后跟toArray
,然后使用deep
方法过滤掉第一行数据帧。
//Method 3
DF.filter(_ => _.toSeq.toArray.deep!=top_row.toSeq.toArray.deep)
如果有帮助还原。感谢!!!
答案 1 :(得分:2)
首先,您真的应该使用spark-csv
- 包 - 它可以在创建DataFrame
(或rdd
)时自动过滤掉标头。您只需指定:)
其次,rdds
并非按照您认为的方式排序。调用first
无法保证返回csv文件的第一行。这是你的第一个场景,显然你确实得到了第一排,但如果你认为自己很幸运,那就更好了。此外,从可能非常大的数据集中删除这样的标头效率非常低,因为Spark需要搜索所有行以过滤掉单行。
如果订购对您进行进一步计算很重要,您可以随时进行zipWithIndex
。这样,您就可以对rdd
进行排序以保留排序。
答案 2 :(得分:2)
有办法删除标题,而不是深度比较:
data = sc.textFile('path_to_data')
header = data.first() #extract header
data = data.filter(lambda x:x !=header) #filter out header
答案 3 :(得分:0)
我找到了另一种方法,它比我使用的过滤方法更有效。将其作为其他人的答案发布可能会发现它有用:
rdd.mapPartitionsWithIndex { (idx, iter) => if (idx == 0) iter.drop(1) else iter }