如何跳过Spark中CSV文件的标题?

时间:2015-01-09 06:21:21

标签: scala csv apache-spark

假设我提供了三个文件路径到Spark上下文来读取,每个文件在第一行中都有一个模式。我们如何从标题中跳过架构线?

val rdd=sc.textFile("file1,file2,file3")

现在,我们如何跳过此rdd中的标题行?

12 个答案:

答案 0 :(得分:87)

data = sc.textFile('path_to_data')
header = data.first() #extract header
data = data.filter(row => row != header)   #filter out header

答案 1 :(得分:60)

如果第一条记录中只有一个标题行,那么过滤它的最有效方法是:

rdd.mapPartitionsWithIndex {
  (idx, iter) => if (idx == 0) iter.drop(1) else iter 
}

如果有许多文件中包含许多标题行,这当然没有用。你可以用这种方式结合三个RDD。

你也可以只写一个filter,它只匹配一个可能是标题的行。这很简单,但效率较低。

Python等价物:

from itertools import islice

rdd.mapPartitionsWithIndex(
    lambda idx, it: islice(it, 1, None) if idx == 0 else it 
)

答案 2 :(得分:54)

在Spark 2.0中,CSV阅读器内置于Spark中,因此您可以按如下方式轻松加载CSV文件:

spark.read.option("header","true").csv("filePath")

答案 3 :(得分:12)

Spark 2.0 开始,你可以使用 SparkSession 来完成这一工作:

val spark = SparkSession.builder.config(conf).getOrCreate()

然后@SandeepPurohit说:

val dataFrame = spark.read.format("CSV").option("header","true").load(csvfilePath)

我希望它能解决你的问题!

P.S:SparkSession是 Spark 2.0 中引入的新入口点,可在 spark_sql包下找到

答案 4 :(得分:7)

在PySpark中,您可以使用数据框并将标头设置为True:

df = spark.read.csv(dataPath, header=True)

答案 5 :(得分:5)

您可以单独加载每个文件,使用file.zipWithIndex().filter(_._2 > 0)过滤它们,然后联合所有文件RDD。

如果文件数太大,联盟可能会抛出StackOverflowExeption

答案 6 :(得分:3)

使用PySpark中的filter()方法过滤掉第一个列名称以删除标题:

# Read file (change format for other file formats)
contentRDD = sc.textfile(<filepath>)

# Filter out first column of the header
filterDD = contentRDD.filter(lambda l: not l.startswith(<first column name>)

# Check your result
for i in filterDD.take(5) : print (i)

答案 7 :(得分:1)

您可以选择传递给read()命令:

context = new org.apache.spark.sql.SQLContext(sc)

var data = context.read.option("header","true").csv("<path>")

答案 8 :(得分:1)

2018年工作(Spark 2.3)

<强>的Python

df = spark.read
    .option("header", "true")
    .format("csv")
    .schema(myManualSchema)
    .load("mycsv.csv")

<强> Scala的

val myDf = spark.read
  .option("header", "true")
  .format("csv")
  .schema(myManualSchema)
  .load("mycsv.csv")

PD1:myManualSchema是我编写的预定义架构,您可以跳过该部分代码

答案 9 :(得分:0)

或者,您可以使用spark-csv软件包(或者在Spark 2.0中,这或多或少可以本地作为CSV使用)。请注意,这需要每个文件的标题(如您所愿):

schema = StructType([
        StructField('lat',DoubleType(),True),
        StructField('lng',DoubleType(),True)])

df = sqlContext.read.format('com.databricks.spark.csv'). \
     options(header='true',
             delimiter="\t",
             treatEmptyValuesAsNulls=True,
             mode="DROPMALFORMED").load(input_file,schema=schema)

答案 10 :(得分:-2)

//Find header from the files lying in the directory
val fileNameHeader = sc.binaryFiles("E:\\sss\\*.txt",1).map{
    case (fileName, stream)=>
        val header = new BufferedReader(new InputStreamReader(stream.open())).readLine()
        (fileName, header)
}.collect().toMap

val fileNameHeaderBr = sc.broadcast(fileNameHeader)

// Now let's skip the header. mapPartition will ensure the header
// can only be the first line of the partition
sc.textFile("E:\\sss\\*.txt",1).mapPartitions(iter =>
    if(iter.hasNext){
        val firstLine = iter.next()
        println(s"Comparing with firstLine $firstLine")
        if(firstLine == fileNameHeaderBr.value.head._2)
            new WrappedIterator(null, iter)
        else
            new WrappedIterator(firstLine, iter)
    }
    else {
        iter
    }
).collect().foreach(println)

class WrappedIterator(firstLine:String,iter:Iterator[String]) extends Iterator[String]{
    var isFirstIteration = true
    override def hasNext: Boolean = {
        if (isFirstIteration && firstLine != null){
            true
        }
        else{
            iter.hasNext
        }
    }

    override def next(): String = {
        if (isFirstIteration){
            println(s"For the first time $firstLine")
            isFirstIteration = false
            if (firstLine != null){
                firstLine
            }
            else{
                println(s"Every time $firstLine")
                iter.next()
            }
        }
        else {
          iter.next()
        }
    }
}

答案 11 :(得分:-2)

对于python开发人员。我用spark2.0测试过。假设您要删除前14行。

sc = spark.sparkContext
lines = sc.textFile("s3://folder_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)