我是Spark和Scala的新手。我有一个拥有大量数据的数据框。架构就像这样。
让我们称之为dataframe empDF
:
id name emp_id code date
1 Andrew D01 C101 2012-06-14
2 James D02 C101 2013-02-26
3 James D02 C102 2013-12-29
4 James D02 C101 2010-09-27
5 Andrew D01 C101 2013-10-12
6 Andrew D01 C102 2011-10-13
我从数据库中将此数据作为DataFrame[Row]
对象读取。现在我必须执行以下步骤:
对于每行代码C101,必须设置大于1的行,对于其他代码级别应为0.如果没有以前的记录,
级别设置为1
。如果存在比该记录早两年或更多年的先前记录,则级别设置为2
。
在此步骤之后,数据框应该如下所示
id name emp_id code date level
1 Andrew D01 C101 2012-06-14 2
2 James D02 C101 2013-02-26 2
3 James D02 C102 2012-12-29 0
4 James D02 C101 2010-09-27 1
5 Andrew D01 C101 2009-10-12 1
6 Andrew D01 C102 2010-10-13 0
第一行和第二行的级别为2
,因为此员工的记录较旧,两行之间的日期差异超过两年。级别为1
的行是因为没有前一个日期的记录,级别为“0”的行是因为我们已将所有代码标记为0级别而不是C101
现在对于级别为2的行,我们必须检查如果代码C102在去年适用于那些员工,如果应用然后将级别设置为3,否则不要更改级别。在最终结果数据帧中,应删除除代码C101之外的所有行。
完成上述两个步骤后,生成的数据框应如下所示:
id name emp_id code date level
1 Andrew D01 C101 2012-06-14 2
2 James D02 C101 2013-02-26 3
4 James D02 C101 2010-09-27 1
5 Andrew 2013 C101 2013-10-12 1
请注意,第一行的级别为2
,因为该员工在去年内没有C102,但第二行在去年内有C102。
如何使用数据框api在Scala中执行此操作,以及map
,flatmap
,reduce
等函数?
答案 0 :(得分:2)
您可以使用window functions:
\
答案 1 :(得分:0)
// Input data
val df = {
import org.apache.spark.sql._
import org.apache.spark.sql.types._
import scala.collection.JavaConverters._
import java.time.LocalDate
val simpleSchema = StructType(
StructField("id", IntegerType) ::
StructField("name", StringType) ::
StructField("emp_id", StringType) ::
StructField("code", StringType) ::
StructField("date", DateType) :: Nil)
val data = List(
Row(1, "Andrew", "D01", "C101", java.sql.Date.valueOf(LocalDate.of(2012, 6, 14))),
Row(2, "James", "D02", "C101", java.sql.Date.valueOf(LocalDate.of(2013, 2, 26))),
Row(3, "James", "D02", "C102", java.sql.Date.valueOf(LocalDate.of(2013, 12, 29))),
Row(4, "James", "D02", "C101", java.sql.Date.valueOf(LocalDate.of(2010, 9, 27)))
)
spark.createDataFrame(data.asJava, simpleSchema)
}
df.show()
// Filter and level calculation.
val df2 = df.filter(col("code") === "C101").
withColumn("level", when(datediff(col("date"), min(col("date")).over(Window.partitionBy("emp_id"))) >= 365 * 2, 2).otherwise(1))
df2.show()