如何从PySpark中的RDD中删除行?特别是第一行,因为它往往包含我的数据集中的列名。通过仔细阅读API,我似乎无法找到一种简单的方法来实现这一目标。当然我可以通过Bash / HDFS来做到这一点,但我只是想知道是否可以在PySpark中完成。
答案 0 :(得分:20)
特定于PySpark:
根据@maasg,您可以这样做:
header = rdd.first()
rdd.filter(lambda line: line != header)
但它在技术上并不正确,因为您可以排除包含数据和标题的行。但是,这似乎对我有用:
def remove_header(itr_index, itr):
return iter(list(itr)[1:]) if itr_index == 0 else itr
rdd.mapPartitionsWithIndex(remove_header)
类似地:
rdd.zipWithIndex().filter(lambda tup: tup[1] > 0).map(lambda tup: tup[0])
我是Spark的新手,因此无法智能地评论哪一个最快。
答案 1 :(得分:18)
AFAIK没有'简单'的方法来做到这一点。
这应该可以解决问题:
val header = data.first
val rows = data.filter(line => line != header)
答案 2 :(得分:5)
在PySpark(Python API)中实现这一目标的简单方法,假设您使用的是Python 3:
noHeaderRDD = rawRDD.zipWithIndex().filter(lambda row_index: row_index[1] > 0).keys()
答案 3 :(得分:2)
我使用各种解决方案进行了一些分析,并具有以下内容
群集配置
700万行,4列
#Solution 1
# Time Taken : 40 ms
data=sc.TextFile('file1.txt')
firstRow=data.first()
data=data.filter(lambda row:row != firstRow)
#Solution 2
# Time Taken : 3 seconds
data=sc.TextFile('file1.txt')
def dropFirstRow(index,iterator):
return iter(list(iterator)[1:]) if index==0 else iterator
data=data.mapPartitionsWithIndex(dropFirstRow)
#Solution 3
# Time Taken : 0.3 seconds
data=sc.TextFile('file1.txt')
def dropFirstRow(index,iterator):
if(index==0):
for subIndex,item in enumerate(iterator):
if subIndex > 0:
yield item
else:
yield iterator
data=data.mapPartitionsWithIndex(dropFirstRow)
我认为解决方案3是最具扩展性的
答案 4 :(得分:1)
我个人认为只使用过滤器来摆脱这些东西是最简单的方法。但根据你的评论,我有另一种方法。 Glom RDD所以每个分区都是一个数组(我假设每个分区有1个文件,每个文件的顶部都有违规行),然后跳过第一个元素(这是scala api)。
data.glom().map(x => for (elem <- x.drop(1){/*do stuff*/}) //x is an array so just skip the 0th index
请记住,RDD的一个重要特性是它们是不可变的,因此自然地删除一行是一件棘手的事情
<强>更新强>
更好的解决方案
rdd.mapPartions(x => for (elem <- x.drop(1){/*do stuff*/} )
与glom相同但没有将所有内容放入数组的开销,因为在这种情况下x是迭代器
答案 5 :(得分:1)
我已经测试过spark2.1。假设你想要在不知道文件列数的情况下删除前14行。
sc = spark.sparkContext
lines = sc.textFile("s3://location_of_csv")
parts = lines.map(lambda l: l.split(","))
parts.zipWithIndex().filter(lambda tup: tup[1] > 14).map(lambda x:x[0])
withColumn是一个df函数。所以下面的内容不适用于上面使用的RDD样式。
parts.withColumn("index",monotonically_increasing_id()).filter(index > 14)