spark scala中的固定长度解析
Fixed length parsing in spark scala
我已经创建了数据框,输入是这样的:
+-----------------------------------+
|value |
+-----------------------------------+
|1 PRE123 21 |
|2 TEST 32 |
|7 XYZ .7 |
+-----------------------------------+
并且根据下面的元数据信息,我们需要拆分上面的数据框并创建一个新的数据框,具有列名 id、name 和 class 并且它开始并在此给出索引位置json 元数据。
{
"columnName": "id",
"start": 1,
"end": 2
},
{
"columnName": "name",
"start": 5,
"end": 10
},
{
"columnName": "class",
"start": 20,
"end": 22
}
输出:
+---+------+-----+
| id| name|class|
+---+------+-----+
| 1|PRE123| 21|
| 2| TEST| 32|
| 7| XYZ| .7|
+---+------+-----+
为了加载 df,我创建了列表:
list.+=(loadedDF.col("value").substr(fixedLength.getStart, (fixedLength.getEnd - fixedLength.getStart)).alias(fixedLength.getColumnName))
然后根据这个列表,我创建了数据框
var df: DataFrame = loadedDF.select(list: _*)
需要了解从元数据创建数据框的更好方法。
由于创建的列表会将所有数据带到驱动程序节点。
如果我理解正确,你的要求是尝试从由任意数量的空格分隔的字符串中提取列。
这是一个带有 substr 函数的解决方案:
val df = Seq(
("1 PRE123 21"),
("2 TEST 32"),
("7 XYZ .7"))
.toDF("value")
val colMetadata = Map("id" -> (1,2), "name" -> (5,10), "class" -> (20,22))
val columns = colMetadata.map { case (cname, meta) =>
val len = meta._2 - meta._1
$"value".substr(meta._1, len).as(cname)
}.toSeq
df.select(columns:_*).show
当您没有使用拆分函数的列边界时的通用解决方案:
import org.apache.spark.sql.functions.split
val df = Seq(
("1 PRE123 21"),
("2 TEST 32"),
("7 XYZ .7"))
.toDF("value")
val colNames = Seq("id", "name", "class")
val columns = colNames.zipWithIndex.map { case (cname, idx) =>
split($"value", "\s+").getItem(idx).as(cname)
}
df.select(columns:_*).show
输出:
+---+------+-----+
| id| name|class|
+---+------+-----+
| 1|PRE123| 21|
| 2| TEST| 32|
| 7| XYZ| .7|
+---+------+-----+
请注意,我使用 \s+
作为分隔符。这表示 一个或多个空格 .
的正则表达式
我已经创建了数据框,输入是这样的:
+-----------------------------------+
|value |
+-----------------------------------+
|1 PRE123 21 |
|2 TEST 32 |
|7 XYZ .7 |
+-----------------------------------+
并且根据下面的元数据信息,我们需要拆分上面的数据框并创建一个新的数据框,具有列名 id、name 和 class 并且它开始并在此给出索引位置json 元数据。
{
"columnName": "id",
"start": 1,
"end": 2
},
{
"columnName": "name",
"start": 5,
"end": 10
},
{
"columnName": "class",
"start": 20,
"end": 22
}
输出:
+---+------+-----+
| id| name|class|
+---+------+-----+
| 1|PRE123| 21|
| 2| TEST| 32|
| 7| XYZ| .7|
+---+------+-----+
为了加载 df,我创建了列表:
list.+=(loadedDF.col("value").substr(fixedLength.getStart, (fixedLength.getEnd - fixedLength.getStart)).alias(fixedLength.getColumnName))
然后根据这个列表,我创建了数据框
var df: DataFrame = loadedDF.select(list: _*)
需要了解从元数据创建数据框的更好方法。 由于创建的列表会将所有数据带到驱动程序节点。
如果我理解正确,你的要求是尝试从由任意数量的空格分隔的字符串中提取列。
这是一个带有 substr 函数的解决方案:
val df = Seq(
("1 PRE123 21"),
("2 TEST 32"),
("7 XYZ .7"))
.toDF("value")
val colMetadata = Map("id" -> (1,2), "name" -> (5,10), "class" -> (20,22))
val columns = colMetadata.map { case (cname, meta) =>
val len = meta._2 - meta._1
$"value".substr(meta._1, len).as(cname)
}.toSeq
df.select(columns:_*).show
当您没有使用拆分函数的列边界时的通用解决方案:
import org.apache.spark.sql.functions.split
val df = Seq(
("1 PRE123 21"),
("2 TEST 32"),
("7 XYZ .7"))
.toDF("value")
val colNames = Seq("id", "name", "class")
val columns = colNames.zipWithIndex.map { case (cname, idx) =>
split($"value", "\s+").getItem(idx).as(cname)
}
df.select(columns:_*).show
输出:
+---+------+-----+
| id| name|class|
+---+------+-----+
| 1|PRE123| 21|
| 2| TEST| 32|
| 7| XYZ| .7|
+---+------+-----+
请注意,我使用 \s+
作为分隔符。这表示 一个或多个空格 .