我在Spark中有一个数据框:
customer | age
--------------------
A 25
B 17
C 8
客户和年龄列都是字符串类型。
所以,
(0>=age<=10)
,那么我想将其映射到0
(11>=age<=20)
,那么我想将其映射到1
(21>=age<=30)
,那么我想将其映射到2
使新数据框成为:
customer_new | age_new
--------------------
A 2
B 1
C 0
此处新数据框customer_new
的类型为String
,age_new
的类型为Integer
。
答案 0 :(得分:0)
您可以使用withColumn
多个when
功能来提供条件。请尝试以下代码,
df.withColumn("customer_new", $"customer")
.withColumn("age_new",
when($"age" >= 0 && $"age" <= 10, 0).
when($"age" >= 11 && $"age" <= 20, 1).
when($"age" >= 21 && $"age" <= 30, 2)).
select("customer_new", "age_new").show()
它会给你以下输出
+------------+-------+
|customer_new|age_new|
+------------+-------+
| A| 2|
| B| 1|
| C| 0|
+------------+-------+
答案 1 :(得分:-1)
第一步是将列类型转换为double。
val df = Seq(("a", "25"), ("b", "17"), ("c", "8")).toDF("customer", "age")
.withColumn("age", $"age".cast(DoubleType))
然后,如果您只有几个条件,则可以使用when
和otherwise
。例如,使用输入数据和条件:
val df2 = df.withColumn("age_new",
when($"age" <= 10, 0.0).
when($"age" <= 20, 1.0).
when($"age" <= 30, 2.0).
otherwise(3.0))
如果有很多条件,那么使用when
会很烦人。在这种情况下,Bucketizer
是一个很好的选择:
val splits = Array(0.0, 10.0, 20.0, 30.0)
val bucketizer = new Bucketizer().setInputCol("age").setOutputCol("age_new").setSplits(splits)
val df3 = bucketizer.transform(df)
两种情况下的输出相同(age
列可以使用select
或drop
删除:
+--------+----+-------+
|customer| age|age_new|
+--------+----+-------+
| a|25.0| 2.0|
| b|17.0| 1.0|
| c| 8.0| 0.0|
+--------+----+-------+
答案 2 :(得分:-1)
始终建议尽可能使用内置函数。由于其他人已经建议过功能,您可以尝试使用地图功能
import sqlContext.implicits._
df.map(row => {
val age = row.getAs[String]("age").trim.toInt
(row.getAs[String]("customer"), if(age >= 0 && age <= 10) "0" else if(age >= 11 && age <= 20) "1" else if(age >= 21 && age <= 30) "2" else null)
})
.toDF("customer_new", "age_new")
应该给你
+------------+-------+
|customer_new|age_new|
+------------+-------+
|A |2 |
|B |1 |
|C |0 |
+------------+-------+