【发布时间】:2019-09-15 06:55:19
【问题描述】:
我有一个这样的 pyspark 数据框,
+----------+--------+----------+----------+
|id_ | p |d1 | d2 |
+----------+--------+----------+----------+
| 1 | A |2018-09-26|2018-10-26|
| 2 | B |2018-06-21|2018-07-19|
| 2 | C |2018-07-13|2018-10-07|
| 2 | B |2018-12-31|2019-02-27|
| 2 | A |2019-01-28|2019-06-25|
-------------------------------------------
我必须从这个数据帧中制作一个这样的数据帧,
+----------+--------+----------+----------+
|id_ | q |d1 | d2 |
+----------+--------+----------+----------+
| 1 | A |2018-09-26|2018-10-26|
| 2 | B |2018-06-21|2018-07-12|
| 2 | B C |2018-07-13|2018-07-19|
| 2 | C |2018-07-20|2019-10-07|
| 2 | B |2018-12-31|2019-01-27|
| 2 | B A |2019-01-28|2019-02-27|
| 2 | A |2019-02-28|2019-06-25|
-------------------------------------------
类似于查找特定id_ 的数据中从何时到何时出现的p 值。如果同一天有多个p,那么两者都应该出现在数据中,并用空格分隔。
我尝试通过在min(d1) 和max(d2) 范围内创建每个日期并相应地填充它们来做到这一点。从该数据框中,经过一些融合和分组后,我可以获得所需的结果。
但是这个过程需要很长时间并且效率很低。
我正在寻找一种有效的方法来执行这项任务。
我还可以有更复杂的重叠情况,即两个以上 p 值之间的重叠。
请参阅下面的示例数据,
+----------+--------+----------+----------+
|id_ | p |d1 | d2 |
+----------+--------+----------+----------+
| 1 | A |2018-09-26|2018-10-26|
| 2 | B |2018-06-21|2018-07-19|
| 2 | C |2018-06-27|2018-07-07|
| 2 | A |2018-07-02|2019-02-27|
| 2 | A |2019-03-28|2019-06-25|
-------------------------------------------
这必须转换成,
+----------+--------+----------+----------+
|id_ | q |d1 | d2 |
+----------+--------+----------+----------+
| 1 | A |2018-09-26|2018-10-26|
| 2 | B |2018-06-21|2018-06-26|
| 2 | B C |2018-06-27|2018-07-01|
| 2 | B C A |2018-07-02|2018-07-07|
| 2 | A B |2018-07-08|2018-07-19|
| 2 | A |2018-07-20|2019-02-27|
| 2 | A |2019-03-28|2019-06-25|
-------------------------------------------
q 中各个项目的顺序无关紧要。即,如果 A、B 和 C 重叠。它可以显示为 A B C 或 B C A 或 A C B 等等。
我还添加了一个难以实现的边缘案例,即d2 == lead(d1).over(window)。在这种情况下,可以安全地假设p 的值是不同的。即p != lead(p).over(window)。
+---+---+----------+----------+
|id_| p | d1 | d2 |
+---+---+----------+----------+
|100| 12|2013-10-16|2014-01-17|
|100| 12|2014-01-20|2014-04-15|
|100| 12|2014-04-22|2014-05-19|
|100| 12|2014-05-22|2014-06-19|
|100| 12|2014-07-23|2014-09-18|
|100| 12|2014-09-23|2014-12-18|
|100| 12|2014-12-20|2015-01-16|
|100| 12|2015-01-23|2015-02-19|
|100| 12|2015-02-21|2015-04-20|
|100| 7 |2015-04-20|2015-05-17|
|100| 7 |2015-05-19|2015-06-15|
|100| 7 |2015-06-18|2015-09-01|
|100| 7 |2015-09-09|2015-11-26|
+---+---+----------+----------+
在上述数据中,倒数第 4 行和第 5 行显示了这种情况。在这种情况下,预期的结果是,
+---+-----+----------+----------+
|id_| p | d1 | d2 |
+---+-----+----------+----------+
|100| 12 |2013-10-16|2014-01-17|
|100| 12 |2014-01-20|2014-04-15|
|100| 12 |2014-04-22|2014-05-19|
|100| 12 |2014-05-22|2014-06-19|
|100| 12 |2014-07-23|2014-09-18|
|100| 12 |2014-09-23|2014-12-18|
|100| 12 |2014-12-20|2015-01-16|
|100| 12 |2015-01-23|2015-02-19|
|100| 12 |2015-02-21|2015-04-19|
|100| 12 7|2015-04-20|2015-04-20|
|100| 7 |2015-04-21|2015-05-17|
|100| 7 |2015-05-19|2015-06-15|
|100| 7 |2015-06-18|2015-09-01|
|100| 7 |2015-09-09|2015-11-26|
+---+-----+----------+----------+
下面给出了相同情况的另一个例子,
+---+---+----------+----------+
|id_| p | d1 | d2 |
+---+---+----------+----------+
|101| 12|2015-02-24|2015-03-23|
|101| 12|2015-04-01|2015-05-19|
|101| 12|2015-05-29|2015-06-25|
|101| 12|2015-07-03|2015-07-30|
|101| 12|2015-09-02|2015-09-29|
|101| 12|2015-10-02|2015-10-29|
|101| 9 |2015-10-29|2015-11-11|
|101| 9 |2015-11-25|2015-12-22|
+---+---+----------+----------+
同样的预期结果是,
+---+-----+----------+----------+
|id_| q | d1 | d2 |
+---+-----+----------+----------+
|101| 12 |2015-02-24|2015-03-23|
|101| 12 |2015-04-01|2015-05-19|
|101| 12 |2015-05-29|2015-06-25|
|101| 12 |2015-07-03|2015-07-30|
|101| 12 |2015-09-02|2015-09-29|
|101| 12 |2015-10-02|2015-10-28|
|101| 12 9|2015-10-29|2015-10-29|
|101| 9 |2015-10-30|2015-11-11|
|101| 9 |2015-11-25|2015-12-22|
+---+---+------------+----------+
【问题讨论】:
-
嗨 - 数据集大小是多少?
-
几百万行。不到十亿
-
请注意组合可以在两个以上的 p 值之间。像 A B C 或 A B C D 等等
-
@SreeramTP,调整代码以反映设置聊天/cmets 中讨论的边界的逻辑。请查看并让我知道任何问题。此外,由于添加了字符串操作,这将比之前的代码慢。
-
@SreeramTP 它看起来可以使用我的帖子的第一个版本进行预处理,并在使用我的帖子中的代码逻辑之前对测试条件进行一些修改。