sc.textFile(path)允许读取HDFS文件,但它不接受参数(比如跳过多行,has_headers,......)。
在学习星火" O' Reilly电子书,建议使用以下函数读取CSV(例5-12.Python加载CSV示例)
import csv
import StringIO
def loadRecord(line):
"""Parse a CSV line"""
input = StringIO.StringIO(line)
reader = csv.DictReader(input, fieldnames=["name", "favouriteAnimal"])
return reader.next()
input = sc.textFile(inputFile).map(loadRecord)
我的问题是关于如何选择行"采取":
我在这里看到一些不错的解决方案:select range of elements但我想看看是否有更简单的事情。
THX!
答案 0 :(得分:17)
不要担心加载您不需要的行/行。当你这样做时:
input = sc.textFile(inputFile)
您没有加载该文件。您只是获得了一个允许您对文件进行操作的对象。所以为了提高效率,最好只考虑获得你想要的东西。例如:
header = input.take(1)[0]
rows = input.filter(lambda line: line != header)
请注意,这里我没有使用索引来引用我想要删除的行,而是使用它的值。这有副作用,其他具有此值的行也将被忽略,但更符合Spark的精神,因为Spark会在节点的不同部分分发您的文本文件,并且行号的概念在每个分区中都会丢失。这也是为什么在Spark(Hadoop)中不容易做到的原因,因为每个分区都应该被认为是独立的,并且全局行号会打破这个假设。
如果您确实需要使用行号,我建议您将它们添加到Spark之外的文件中(请参阅here),然后只在Spark中按此列进行过滤。
修改:根据@Daniel Darabos的建议添加了zipWithIndex
解决方案。
sc.textFile('test.txt')\
.zipWithIndex()\ # [(u'First', 0), (u'Second', 1), ...
.filter(lambda x: x[1]!=5)\ # select columns
.map(lambda x: x[0])\ # [u'First', u'Second'
.collect()