我在HDFS上有一个很大的分布式文件,每次我使用带有spark-csv包的sqlContext时,它首先加载整个文件,这需要相当长的时间。
df = sqlContext.read.format('com.databricks.spark.csv').options(header='true', inferschema='true').load("file_path")
现在因为我只是想做一些快速检查,所有我需要的是整个文件的少数/任意n行。
df_n = sqlContext.read.format('com.databricks.spark.csv').options(header='true', inferschema='true').load("file_path").take(n)
df_n = sqlContext.read.format('com.databricks.spark.csv').options(header='true', inferschema='true').load("file_path").head(n)
但所有这些都在文件加载完成后运行。我不能在读取文件本身时限制行数吗?我指的是spark-csv中n_rows等效的pandas,比如:
pd_df = pandas.read_csv("file_path", nrows=20)
或者可能是火花实际上没有加载文件的情况,第一步,但在这种情况下,为什么我的文件加载步骤花费了太多时间呢?
我想要
df.count()
只给我n
而不是所有行,是否可能?
答案 0 :(得分:13)
您可以使用limit(n)
。
sqlContext.format('com.databricks.spark.csv') \
.options(header='true', inferschema='true').load("file_path").limit(20)
这只会加载20行。
答案 1 :(得分:8)
我的理解是,spark-csv模块不直接支持读取几行,并且作为解决方法,您可以将文件作为文本文件读取,占用尽可能多的行想要并将其保存到某个临时位置。保存这些行后,您可以使用spark-csv来读取行,包括inferSchema
选项(如果您处于探索模式,可能需要使用它)。
val numberOfLines = ...
spark.
read.
text("myfile.csv").
limit(numberOfLines).
write.
text(s"myfile-$numberOfLines.csv")
val justFewLines = spark.
read.
option("inferSchema", true). // <-- you are in exploration mode, aren't you?
csv(s"myfile-$numberOfLines.csv")
答案 2 :(得分:2)
在所有方面,不推断架构并使用limit(n)
为我工作。
f_schema = StructType([
StructField("col1",LongType(),True),
StructField("col2",IntegerType(),True),
StructField("col3",DoubleType(),True)
...
])
df_n = sqlContext.read.format('com.databricks.spark.csv').options(header='true').schema(f_schema).load(data_path).limit(10)
注意:如果我们使用inferschema='true'
,那么它也会同时使用,也许因此也是旧的。
但如果我们不了解架构,Jacek Laskowski解决方案也能很好地运作。 :)
答案 3 :(得分:1)
Jacek Laskowski 给出的解决方案运行良好。在下面展示内存中的变体。
我最近遇到了这个问题。我正在使用数据块并有一个巨大的 csv 目录(200 个文件,每个文件 200MB)
我本来就有
val df = spark.read.format("csv")
.option("header", true)
.option("sep", ",")
.option("inferSchema", true)
.load("dbfs:/huge/csv/files/in/this/directory/")
display(df)
这花了很多时间(10 分钟以上),但后来我将其更改为以下,它立即运行(2 秒)
val lines = spark.read.text("dbfs:/huge/csv/files/in/this/directory/").as[String].take(1000)
val df = spark.read
.option("header", true)
.option("sep", ",")
.option("inferSchema", true)
.csv(spark.createDataset(lines))
display(df)
推断文本格式的模式很困难,可以通过这种方式为 csv 和 json(但如果它是多行 json)格式完成。
答案 4 :(得分:0)
自PySpark 2.3起,您可以简单地将数据加载为文本,限制并在结果上应用csv阅读器:
(spark
.read
.options(inferSchema="true", header="true")
.csv(
spark.read.text("/path/to/file")
.limit(20) # Apply limit
.rdd.flatMap(lambda x: x))) # Convert to RDD[str]
Scala对应版本自Spark 2.2可用:
spark
.read
.options(Map("inferSchema" -> "true", "header" -> "true"))
.csv(spark.read.text("/path/to/file").limit(20).as[String])
在Spark 3.0.0或更高版本中,也可以应用限制并使用from_csv
函数,但是它需要一个架构,因此可能不符合您的要求。
答案 5 :(得分:0)
由于我没有在答案中看到该解决方案,所以纯 SQL 方法对我有用:
df = spark.sql("SELECT * FROM csv.`/path/to/file` LIMIT 10000")
如果没有标题,列将被命名为 _c0、_c1 等。不需要架构。