【问题标题】:How to associate dates with a count or an integer [duplicate]如何将日期与计数或整数相关联[重复]
【发布时间】:2018-12-03 20:12:23
【问题描述】:

我有一个DataFrame,其中包含“id”和“date”列。日期格式为 yyyy-mm-dd 这里是一个例子:

+---------+----------+
|  item_id|        ds|
+---------+----------+
| 25867869|2018-05-01|
| 17190474|2018-01-02|
| 19870756|2018-01-02|
|172248680|2018-07-29|
| 41148162|2018-03-01|
+---------+----------+

我想创建一个新列,其中每个日期都与一个从 1 开始的整数相关联。这样最小(最早的)日期获得整数 1 ,下一个(最早的第二个日期)被分配给 2 等等。 .

我希望我的DataFrame 看起来像这样...:

+---------+----------+---------+
|  item_id|        ds|   number|
+---------+----------+---------+
| 25867869|2018-05-01|        3|
| 17190474|2018-01-02|        1|
| 19870756|2018-01-02|        1|
|172248680|2018-07-29|        4|
| 41148162|2018-03-01|        2|
+---------+----------+---------+

解释

2018 年 1 月 2 日日期最早,因此其编号为 1。由于有 2 行具有相同的日期,因此 1 位于两次。在 2018-01-02 之后,下一个日期是 2018-03-01,因此它的编号是 2,依此类推...我怎样才能创建这样的列?

【问题讨论】:

    标签: scala apache-spark apache-spark-sql


    【解决方案1】:

    您应该创建一个函数来获取没有数字的最旧查询,例如:

    SELECT * FROM tablename WHERE number IS NULL ORDER BY ds ASC

    然后在你得到最大数字的地方进行另一个查询:

    SELECT * FROM tablename ORDER BY number DESC

    如果两个查询具有相同的日期,则使用相同的数字更新表:

    UPDATE tablename SET number = 'greatest number from first query' WHERE ds = 'the date from first query'

    或者如果日期不同,则相同,但在数字上加 1:

    UPDATE tablename SET number= 'greatest number from first query' + 1 WHERE ds = 'the date from first query'

    要完成这项工作,您应该首先将数字 1 分配给最旧的条目。 您应该循环执行此操作,直到第一个查询(检查是否有任何未设置的数字)为空。 第一个查询假设空列全部为空,如果是另一种情况,则应更改 WHERE 条件以检查该列何时为空。

    【讨论】:

      【解决方案2】:

      这可以通过dense_rank 中的Window 函数来实现。

      import org.apache.spark.sql.expressions.Window
      import org.apache.spark.sql.functions._
      val win = Window.orderBy(to_date(col("ds"),"yyyy-MM-dd").asc)
      val df1 = df.withColumn("number", dense_rank() over win)
      

      df1 将根据需要包含 number 列。

      注意:to_date(col("ds"),"yyyy-MM-dd") 是强制性的,否则它将被视为字符串,并且无法达到目的。

      【讨论】:

      • 它的工作速度很慢,因为我的数据是在 ds 上分区的。在运行代码时,它还会显示警告,“WARN WindowExec:没有为 Window 操作定义分区!将所有数据移动到单个分区,这可能会导致严重的性能下降。” ,你能帮我解决这个问题吗?
      • 由于您的要求是整个表数据中的整数按照日期递增的顺序,因此需要将整个数据视为单个分区........如果您只需要唯一的数字(而不是连续的数字),有更快的选择。
      • 如果我们找出最早的日期并开始使用“日期差异”功能找出日差,这不会造成任何问题,因为我的日期数据非常密集,几乎所有日期都包含在其中.你能帮我在 scala 中编写我的想法吗?
      • 我觉得这很值得一试。虽然你可能得不到连续的数字,但我希望它能满足你的要求
      猜你喜欢
      • 1970-01-01
      • 2014-08-12
      • 1970-01-01
      • 2012-09-27
      • 1970-01-01
      • 2015-06-10
      • 1970-01-01
      • 1970-01-01
      • 2021-07-05
      相关资源
      最近更新 更多