先说个题外话,如何给hive表增加一个列,并且该把该列的所有字段设为’China’?
如果仅仅是增加一列倒是很简单:
alter table test add columns(flag string)
可要把这个flag字段全部设置为China,看起来的确是有点难度,因为往Hive表中装载数据的唯一途径就是使用一种“大量”的数据装载操作(如何往Hive表加载数据请参考),这个时候,如果数据集中本来就没有flag对应的数据,难道非要手动把China添加上去?这种情况,可以通过静态分区就能够解决:
load data local inpath '/data/test.txt' overwrite into table test partition (flag = 'China')
有人说,这不扯淡吗?如果这个China字段,并不是我们经常需要访问的字段,何须作为分区字段呢?的确是这样的,这个时候还可以通过下面的方式来解决这个问题:
insert into table test1 select id, name,'China' as flag from test;
好了步入正题:如何向Spark的DataFrame增加一列数据
准备数据集:
张三,23
李四,24
王五,25
赵六,26
程序入口SparkSession和加载数据代码这里不再描述:
val spark = SparkSession
.builder()
.appName(this.getClass.getSimpleName)
.master(master = "local[*]")
.getOrCreate()
import spark.implicits._
val df = spark.read.textFile("./data/clm")
.map(_.split(","))
.map(x => (x(0), x(1)))
.toDF("name", "age")
.cache()
通过添加列或替换具有相同名称的现有列来返回新的数据集
column的表达式只能引用此数据集提供的属性。 添加引用其他数据集的列是错误的
新的列只能通过现有列转换得到,这个就有点局限,不过也能解决一部分问题:
比如,我想再增加一列为所有age增加1作为新的一列:
df.withColumn("new_age", col = df("age") + 1).show()
结果:
+----+---+-------+
|name|age|new_age|
+----+---+-------+
|张三| 23| 24.0|
|李四| 24| 25.0|
|王五| 25| 26.0|
|赵六| 26| 27.0|
+----+---+-------+
那么如果我想像前言中做那样的操作怎么办?
df.createTempView(viewName = "view1")
import spark.sql
sql(sqlText = "select name,age,'一班' as class from view1").show()
结果:
+----+---+-----+
|name|age|class|
+----+---+-----+
|张三| 23| 一班|
|李四| 24| 一班|
|王五| 25| 一班|
|赵六| 26| 一班|
+----+---+-----+
该函数官网的描述是:一个列表达式,用于生成单调递增的64位整数
import org.apache.spark.sql.functions._
df.withColumn("id", monotonically_increasing_id()).show()
结果:
+----+---+---+
|name|age| id|
+----+---+---+
|张三| 23| 0|
|李四| 24| 1|
|王五| 25| 2|
|赵六| 26| 3|
+----+---+---+
我们发现它是从0开始单调递增的,如果想从1开始递增:
import org.apache.spark.sql.functions._
df.withColumn("id", monotonically_increasing_id() + 1).show()
结果:
+----+---+---+
|name|age| id|
+----+---+---+
|张三| 23| 1|
|李四| 24| 2|
|王五| 25| 3|
|赵六| 26| 4|
+----+---+---+