如何将一列从DataFrame中拆分出来,但保持其与初始DataFrame的关联?

时间:2019-03-01 16:00:24

标签: scala apache-spark dataframe

我有一个数据框dataDF,即:

+-------+------+-----+-----+-----------+
|TEST_PK| COL_1|COL_2|COL_3|h_timestamp|
+-------+------+-----+-----+-----------+
|      1| apple|   10| 1.79|       1111|
|      1| apple|   11| 1.79|       1114|
|      2|banana|   15| 1.79|       1112|
|      2|banana|   16| 1.79|       1115|
|      3|orange|    7| 1.79|       1113|
+-------+------+-----+-----+-----------+

我需要运行此功能:
operation(row, h_timestamp)
在每一行上,但是row不能包含h_timestamp,所以我的第一个想法是像这样拆分数据帧:

val columns = dataDF.drop("h_timestamp")  
val timestamp = dataDF.select("h_timestamp")  

但是当我想对每一行执行该操作时,这没有帮助:

dataDF.map(row => {
  ...
  val rowWithoutTimestamp = ???
  val timestamp = ???
  operation(rowWithoutTimestamp, timestamp)
  ...
})

但是现在这两个数据帧没有链接,我不知道如何为每一行获取正确的时间戳。 TEST_PK列不一定是唯一的。
有没有一种方法可以仅在一行上使用.drop().select()或其他某种方式?
编辑:此外,该表可以具有任意数量的列,但始终具有时间戳列,并且至少还有一个不是时间戳的列

1 个答案:

答案 0 :(得分:0)

由于您似乎有一个主键列,因此只需将带有id列的时间戳插入其自己的数据框中,以便稍后重新加入。

val tsDF = dataDF.select("TEST_PK", "h_timestamp")

然后,将列从dataDF中删除,进行操作,然后将h_timestamp重新加入新的数据框中。

val finalDF = postopDF.join(tsDF, "TEST_PK")

更新

示例代码很有帮助,您应该基本上可以分解行,并使用类似以下内容的值重建新行:

dataDF.map(row => {
  val rowWithoutTimestamp = Row(
    row.getAs[Long]("TEST_PK"),
    row.getAs[String]("COL_1"),
    row.getAs[Long]("COL_2"),
    row.getAs[Double]("COL_3")
  )
  val timestamp = row.getAs[Long]("h_timestamp")
  val result = operation(rowWithoutTimestamp, timestamp)
  Row(result, timestamp)
})

当然,我不确定您的operation()返回什么,因此可能有必要将result分解为单个值,并用这些值和时间戳组成新行。

更新2

好的,这是一个更通用的方法。它将“ h_timestamp以外的所有列”包装到一个结构中,并映射到(struct, ts)元组上。其实比以前的解决方案还优雅。

val cols = df.drop("h_timestamp").columns.toSeq
dataDF
  .select(struct(cols.map(c => col(c)):_*).as("row_no_ts"), $"h_timestamp")
  .map(row => {
    val rowWithoutTimestamp = row.getAs[Row]("row_no_ts")
    val timestamp = row.getAs[Long]("h_timestamp")
    operation(rowWithoutTimestamp, timestamp)
  })

我不确定您是要映射到operation()的输出还是再次与时间戳进行某种组合,但是两者都可以根据需要进行修改。