我在S3中有一个数据集(〜100GB),该数据集带有时间戳,后跟JSON字符串,而不仅仅是纯JSON字符串。此数据被压缩。是否有将数据读入数据帧而不重新格式化数据以删除时间戳的方法?我根本不需要时间戳,可以忽略它。这是数据示例:
2019-06-28T00:00:00.000Z { "a": 123, "b": "456", "c": 789 }
我通常使用胶水库read_from_options
读取数据,但是看不到任何忽略时间戳的选项,只是读入JSON字符串。我不确定是否可以触发任何功能。
答案 0 :(得分:3)
让我们假设,这就是数据的样子-
country|city|json_content
america|chicago|2019-06-28T00:00:00.000Z { "a": 123, "b": "456", "c": 789 }
india|mumbai|2019-06-28T00:00:00.000Z { "a": 123, "b": "456", "c": 789 }
将其读入spark数据框-
val df = spark
.read
.option("header", "true") // Use first line of all files as header
.option("delimiter", "|")
.csv("csv_file_path")
由于压缩了数据,因此,请首先将其读入RDD,如下所示,然后将其转换为DF( 让我知道在RDD到DF的转换中是否需要我的帮助。 )-
val rdd = sc.textFile("myFile.gz")
导入重要功能-
import org.apache.spark.sql.functions._
编写并注册一个UDF,该UDF仅从timestamp + json列中提取json内容
val getJsonContent = udf{input: String => input.substring(input.indexOf("{"))}
应用此UDF并创建最终的数据框-
val finalDf = df.withColumn("json_content",getJsonContent(col("json_content")))
答案 1 :(得分:3)
Anamdeo的答案很好,但是我要强调,由于性能问题,您应该尽可能避免使用UDF。在这种情况下,您可以轻松地使用regexp_extract
将时间戳与您感兴趣的JSON内容分开:
scala> val regex = "([0-9\\-TZ\\.:]+) (\\{.*)"
regex: String = ([0-9\-TZ\.:]+) (\{.*)
scala> val dff = df.withColumn("tstamp", regexp_extract('json_content, regex, 1)).withColumn("json", regexp_extract('json_content, regex, 2)).drop("json_content")
dff: org.apache.spark.sql.DataFrame = [country: string, city: string ... 2 more fields]
scala> dff.show(false)
+-------+-------+------------------------+----------------------------------+
|country|city |tstamp |json |
+-------+-------+------------------------+----------------------------------+
|america|chicago|2019-06-28T00:00:00.000Z|{ "a": 123, "b": "456", "c": 789 }|
|india |mumbai |2019-06-28T00:00:00.000Z|{ "a": 123, "b": "456", "c": 789 }|
+-------+-------+------------------------+----------------------------------+
从这一点开始,如果需要,您可以使用Spark的内置函数,例如from_json
和get_json_object
直接处理JSON数据。