web-dev-qa-db-ja.com

spark-csvパッケージを使用してHDFS上の大きなCSVファイルのn行のみを読み取る方法

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のpandasと同等のn_rowsを参照しています:

pd_df = pandas.read_csv("file_path", nrows=20)

または、sparkが実際にファイルをロードしない場合、最初のステップですが、この場合、ファイルのロードステップに時間がかかりすぎるのはなぜですか?

が欲しいです

df.count()

すべての行ではなくnのみを提供することは可能ですか?

12
Abhishek

limit(n)を使用できます。

sqlContext.format('com.databricks.spark.csv') \
          .options(header='true', inferschema='true').load("file_path").limit(20)

これにより、20行がロードされます。

12
eliasah

私の理解では、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")
9
Jacek Laskowski

スキーマを推測せず、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ソリューションもうまく機能します。 :)

2
Abhishek

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]

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関数ですが、スキーマが必要なので、おそらく要件に適合しません。

0
user10958683