ETL
提取、转换、加载(ETL)是一个三阶段的计算过程,其中数据从输入源提取、转换(包括清理、聚合、导出新值)并加载到输出数据容器中。 在大数据和AI流行的今天,ETL有了更多的用武之地。
下面是来自wikipedia的一个关于ETL的一幅图很好的说明了ETL的主要功能
https://en.wikipedia.org/wiki/Extract,_transform,_load
我有一系列的csv,每个csv是某个基金的信息。 这个文章中,我计划利用ETL把一系列的csv合并为parquet文件,为之后的各种应用提供一个数据源。这个ETL主要功能包括:
1: 加载一系列csv
2:文件的名字是FundPrice<基金id>.csv,所以添加一列把fundid加到数据中
2: 因为csv导入后,查看它的schema 发现类型与数据不太匹配,定义了schema把csv各列数据转换为适当的类型
3:根据csv数据中最近一周数据来计算并添加每周价格平均价格列(一种常见的聚合)
4:保存为parquet文件。因为我的数据比较小,parquet文件建议文件大小在128M到1G之间,我把数据保存到了一个文件中。
import os
from pyspark.sql import SparkSession
from pyspark.sql.functions import input_file_name, regexp_extract, round
from pyspark.sql.window import Window
from pyspark.sql.functions import avg, col
from pyspark.sql.types import StructType, StructField, DateType, DecimalType, StringType, IntegerType
if __name__ == "__main__":
spark = SparkSession \
.builder \
.master("local[3]") \
.appName("sample2") \
.getOrCreate()
csvDF = spark.read \
.format("csv") \
.option("header", "true") \
.load("data/fund/FundPrice*.csv") \
.withColumn("fundid", regexp_extract(input_file_name(), r"FundPrice(\d+)\.csv", 1))
# Define a window specification to calculate the average of the last 5 days
window_spec = Window.partitionBy("fundid").orderBy("date").rowsBetween(-4, 0)
# Add a new column for the average accumulate price, rounded to 3 decimal places
csvDF = csvDF.withColumn("avgAccumulatePrice", round(avg(col("accumulativePrice")).over(window_spec), 3))
print(csvDF.count())
csvDF.show()
print(csvDF.schema.json())
# Define the schema for the Parquet file
parquet_schema = StructType([
StructField("Date", DateType(), True),
StructField("fundid", StringType(), True),
StructField("accumulativePrice", DecimalType(10, 3), True),
StructField("avgAccumulatePrice", DecimalType(10, 3), True),
StructField("isbonus", IntegerType(), True), # Added as IntegerType
StructField("isCash", IntegerType(), True), # Added as IntegerType
StructField("price", DecimalType(10, 3), True), # Added as DecimalType
StructField("bonusPerStock", DecimalType(10, 3), True) # Added as DecimalType
])
# Apply the schema when saving as Parquet
csvDF = csvDF.select(
col("Date").cast(DateType()),
col("fundid"),
col("accumulativePrice").cast(DecimalType(10, 3)),
col("avgAccumulatePrice").cast(DecimalType(10, 3)),
col("isbonus").cast(IntegerType()), # Cast to IntegerType
col("isCash").cast(IntegerType()), # Cast to IntegerType
col("price").cast(DecimalType(10, 3)), # Cast to DecimalType
col("bonusPerStock").cast(DecimalType(10, 3)) # Cast to DecimalType
)
# coalesce(1) is used to save it as one file
csvDF.coalesce(1).write \
.format("parquet") \
.mode("overwrite") \
.option("path", "data/fund/parquet/") \
.save()
parquetDF = spark.read \
.format("parquet") \
.load("data/fund/parquet/*.parquet")
parquetDF.show(5)
print(parquetDF.schema.json())
spark.stop()
下面是运行结果
代码: https://gitee.com/yanghang1977/pyspark/blob/master/Etl.py
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。