我有一個.csv包含幾列的檔案。
以一行為例:
aaa,bbb,{'foo': 'xxx', 'bar': 'zzz'}
我想閱讀它并轉換為以下型別的架構:
field1: String,
field2: String,
field3: Map[String, String]
我可以用這樣的原始型別來做到這一點:
private val someSchema =
StructType(
StructField("field1", StringType, true) ::
StructField("field2", StringType, true) ::
StructField("field3", StringType, true) :: Nil)
spark.read
.format("csv")
.option("header", true)
.schema(someSchema)
.load("path.csv")
但是當涉及到 Map[String, String] 時,它不起作用,因為
執行緒“main”org.apache.spark.sql.AnalysisException 中的例外:CSV 資料源不支持 map<string,string> 資料型別。
我該如何以另一種方式做到這一點?
uj5u.com熱心網友回復:
您需要將其作為字串讀取,然后將其轉換為 MapType。在應用函式將其決議為之前,您可以用雙引號替換單引號field3以獲取有效的 json 字串:from_jsonmap<string,string>
val result = df.withColumn(
"field3",
from_json(
regexp_replace(col("field3"), "'", "\""),
lit("map<string,string>")
)
)
但是,從您的示例來看,檔案中的值似乎沒有轉義,spark 將無法決議它,因為您在 column 的值中有逗號(分隔符)field3。
在這種情況下,您可以將檔案讀取為文本,然后用{}另一個分隔符替換 中的逗號,例如;,拆分,以獲取 3 列并field3使用str_to_map函式將列轉換為映射:
val df = spark.text("/path/file.csv")
val result = df.withColumn(
"value",
split(regexp_replace(col("value"), ",(?=[^{}]*\\})", ";"), ",")
).select(
col("value")(0).as("field1"),
col("value")(1).as("field2"),
regexp_replace(col("value")(2), "[{}' ]", "").as("field3")
).withColumn(
"field3",
expr("str_to_map(field3, ';', ':')")
)
result.show
// ------ ------ ------------------------
//|field1|field2|field3 |
// ------ ------ ------------------------
//|aaa |bbb |[foo -> xxx, bar -> zzz]|
// ------ ------ ------------------------
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/421896.html
標籤:
