我有一个包含大量记录的数据框。在该DF中,一条记录可以重复多次,并且每次更新时,最后更新的字段将具有修改记录的日期。
我们有一组要比较相似ID的行的列。在此比较中,我们要捕获从先前记录更改为当前记录的字段/列,然后在更新记录的“ updated_columns”列中捕获该字段/列。将此第二条记录与第三条记录进行比较,并标识更新的列,并在第三条记录的“ updated_columns”字段中捕获该记录,继续执行相同操作直到该ID的最后一条记录,并对每个具有多个条目的ID执行相同的操作
最初,我们对列进行分组,并从该组列中创建一个哈希,然后与下一行的哈希值进行比较,这有助于我识别具有更新但想要更新的列的记录。
我在这里共享一些数据,这是预期的结果,因此最终数据应该像添加更新的列后的样子(在这里我可以说,使用列Col1,Col2,Col3,col4和Col5进行两行之间的比较):
想要高效地做到这一点。任何人都可以尝试这样的事情。
正在寻求帮助!
〜克里希。
答案 0 :(得分:1)
可以使用window。
想法是按 ID 将数据分组,按 LAST-UPDATED 排序,然后将前一行的值(如果存在)复制到当前行中然后将复制的数据与当前值进行比较。
val data = ... //the dataframe has the columns ID,Col1,Col2,Col3,Col4,Col5,LAST_UPDATED,IS_DELETED
val fieldNames = data.schema.fieldNames.dropRight(1) //1
val columns = fieldNames.map(f => col(f))
val windowspec = Window.partitionBy("ID").orderBy("LAST_UPDATED") //2
def compareArrayUdf() = ... //3
val result = data
.withColumn("cur", array(columns: _*)) //4
.withColumn("prev", lag($"cur", 1).over(windowspec)) //5
.withColumn("updated_columns", compareArrayUdf()($"cur", $"prev")) //6
.drop("cur", "prev") //7
.orderBy("LAST_UPDATED")
备注:
compareArraysUdf 是
def compareArray(cur: mutable.WrappedArray[String], prev: mutable.WrappedArray[String]): String = {
if (prev == null || cur == null) return ""
val res = new StringBuilder
for (i <- cur.indices) {
if (!cur(i).contentEquals(prev(i))) {
if (res.nonEmpty) res.append(",")
res.append(fieldNames(i))
}
}
res.toString()
}
def compareArrayUdf() = udf[String, mutable.WrappedArray[String], mutable.WrappedArray[String]](compareArray)
答案 1 :(得分:0)
您可以将DataFrame或DataSet与其自身连接,将两行ID相同且左行版本为i
且右行版本为{{1 }}。这是一个例子
i+1
然后您可以引用新的DataFrame / DataSet中的列,例如case class T(id: String, version: Int, data: String)
val data = Seq(T("1", 1, "d1-1"), T("1", 2, "d1-2"), T("2", 1, "d2-1"), T("2", 2, "d2-2"), T("2", 3, "d2-3"), T("3", 1, "d3-1"))
data: Seq[T] = List(T(1,1,d1-1), T(1,2,d1-2), T(2,1,d2-1), T(2,2,d2-2), T(2,3,d2-3), T(3,1,d3-1))
val ds = data.toDS
val joined = ds.as("ds1").join(ds.as("ds2"), $"ds1.id" === $"ds2.id" && (($"ds1.version"+1) === $"ds2.version"))
和$"ds1.data
等。
要查找数据从一种版本更改为另一种版本的行,可以执行
$"ds2.data