我有这个数据框
我想根据字母的位置执行子字符串操作,以使输出像这样
为了创建新列,我使用子字符串操作
我已经写了一些如下的spark scala代码
val df=data.toDF("HI")
df.show()
val df1=df.select(col("*"), substring(col("HI"), 0, 2).as("c"))
val df2=df1.select(col("*"), substring(col("HI"), 3, 4).as("d"))
val df3=df2.select(col("*"), substring(col("d"), 3, 4).as("e")).show()
现在我面临的问题
1>我无法获得实际结果
2>即使我能够设法获得结果,这种方法也是错误的,因为创建了很多额外的数据框只是为了获得实际结果
有什么办法可以在单个数据帧上执行多个子字符串操作并稍微优化代码吗?
答案 0 :(得分:0)
substring函数和withColumn应该做到这一点:
import org.apache.spark.sql.functions._
val df = data.toDF("HI")
df.withColumn("c", substring(col("HI"), 0, 2))
.withColumn("d", substring(col("HI"), 3, 2))
.withColumn("e", substring(col("HI"), 5, 2))
.show()
打印
+------+---+---+---+
| HI| c| d| e|
+------+---+---+---+
|abcdef| ab| cd| ef|
|ghijkl| gh| ij| kl|
|mnopqr| mn| op| qr|
|stuvwx| st| uv| wx|
| yz| yz| | |
+------+---+---+---+
看看Dataset.explain的输出,三个字符串操作在一个阶段中一起执行,因此应该没有性能问题:
== Physical Plan ==
*(1) Project [HI#10, substring(HI#10, 0, 2) AS c#12, substring(HI#10, 3, 2) AS d#15, substring(HI#10, 5, 2) AS e#19]
+- *(1) FileScan csv [HI#10] Batched: false, Format: CSV, Location: InMemoryFileIndex[file:/home/.../test.csv], PartitionFilters: [], PushedFilters: [], ReadSchema: struct<HI:string>
(我正在从一个csv文件读取输入数据)
答案 1 :(得分:0)
希望这会有所帮助,
val df= Seq("abcdef", "ghijkl", "mnopqr", "stuvwx", "yz").toDF("mainCol")
df.select(Array(col("mainCol")) ++ (0 to 4 by 2).map(i => concat(split('mainCol, "").getItem(i), split('mainCol, "").getItem(i + 1)).as(s"subColumn$i")): _*).show()