簡體   English   中英

將大量CSV文件轉換為parquet文件

[英]Convert a large number of CSV files to parquet files

我有大量的CSV文件需要轉換成parquet文件,使用pyspark。 一個 CSV 對應一個 Parquet。

輸入:csv 文件:

000.csv
001.csv
002.csv
...

Output:qarquet文件:

000.parquet
001.parquet
002.parquet
...

我目前的解決方案是:

for each_csv in same_folder:
   df = spark.read.csv(each_csv, header = True)
   df.write.parquet(output_folder)

for 循環很昂貴。 有什么方法可以利用 spark 進行批處理嗎? 例如

spark.read.csv(same_folder/ ).write.parquet(output_folder/ )

根據 QuickSilver 的回答,這是我的 PySpark 版本:

spark = SparkSession.builder.master("local[*]").appName("csv_to_parquet").getOrCreate()

# Read csv files into a single data frame and add a column of input file names: 
baseDf = spark.read.csv("input_folder/*.csv").withColumn("input_file_name", input_file_name())

# Convert file names into a list: 
filePathInfo = baseDf.select("input_file_name").distinct().collect() 
filePathInfo_array = list(map(lambda row: row.input_file_name, filePathInfo))

# Write to parquet:  
map(lambda csvFileName: baseDf.filter(col("input_file_name").endsWith(csvFileName)).write.mode('overwrite').parquet(f'output_folder/{csvFileName}'), filePathInfo_array)

您可以按照以下步驟執行以下步驟,以避免在 Spark 中加載多個文件,

  1. 使用源 csv 文件夾加載 dataframe
  2. input_file_name記錄源文件名
  3. 將文件名收集到列表中
  4. 遍歷文件名列表

在文件名列表循環中,

  1. 按文件名過濾 dataframe
  2. 寫入相應的文件

scala 中的 Sudo 工作代碼

import java.nio.file.Paths

import org.apache.spark.sql.{Encoders, SaveMode, SparkSession}
import org.apache.spark.sql.functions._

object ReadWriteToRespCsv {

  def main(args: Array[String]): Unit = {

    val spark = SparkSession.builder.master("local[*]").getOrCreate;

    val baseDf = spark.read.csv("src/main/resources/same_folder/*.csv")
      //Add a column `input_file_name` which records source file name
      .withColumn("input_file_name",input_file_name())

    //Collect the file names into a List
    val filePathInfo = baseDf.select("input_file_name").distinct()
      .map(row=>Paths.get(row.getString(0)).getFileName.toString)(Encoders.STRING).collect()

    //Iterate for file name list
    filePathInfo.foreach(csvFileName => {
      baseDf
        //Filter dataframe by file name
        .filter(col("input_file_name").endsWith(csvFileName) )
        .write
        .mode(SaveMode.Overwrite)
        //Write to respective file
        .parquet(s"src/main/resources/output_folder/${csvFileName}")
    })
  }

}

您可以對 select 文件使用通配模式,也可以提供文件列表。

如果我在文件夾/tmp/file1_csv/file1.csv/tmp/file2_csv/file2.csv中有兩個文件,我可以使用以下

spark.read.option("header", "true").csv("/tmp/file*_csv/*.csv")

或者,如果你有奇怪的路徑,你也可以使用csv方法的重載版本。

val paths = "/dir1/,/dir2/,/dir3/"
val df = spark.read.option("header", "true").csv(paths.split(","): _*)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM