通过根据条目和变量值之间传递的时间量创建唯一 ID 列来对数据帧行进行分组
Group dataframe rows by creating a unique ID column based on the amount of time passed between entries and variable values
当相同的变量以固定的日期间隔出现时,我试图将我的数据框的行分组到“课程”中。当时间频率出现差距或其中一个变量发生变化时,我想给它一个新的课程 ID。
举个例子,我的数据是这样的:
Date Name Item
1 2018-06-02 Johan Apple
2 2018-07-05 Johan Apple
3 2018-08-02 Johan Apple
4 2019-04-15 Johan Apple
5 2019-05-15 Johan Apple
6 2019-05-30 Samantha Orange
7 2019-06-12 Samantha Orange
8 2019-06-27 Samantha Orange
9 2018-02-15 Mary Lemon
10 2018-04-10 Mary Lemon
11 2018-06-12 Mary Lemon
12 2018-08-13 Mary Lime
13 2018-08-27 Mary Lime
14 2017-03-09 George Kiwi
Name
和 Item
的每个不同组合都应该生成一个新的课程 ID。
但是(棘手的部分)如果两个交易之间存在显着的时间差距,而其他变量是常数,则定义为:超过 6月 或 对于 Item
和 Name
那么应该给它一个新的 CourseID
在我的例子中:
- 因为 Johan 在 2018 年 8 月之后休息,之后的交易应该有一个新的
CourseID
。理想情况下,检查未来休息时间的间隔将基于这个新组的平均值。
- 萨曼莎每两周购买一次橙子,没有明显的缺口,因此她的所有交易都会有一个
CourseID
。
- Mary 定期购买柠檬,但随后转为定期购买酸橙,因此这些有两个
CourseID
s。
- George 刚买了一个 Kiwi,所以一个
CourseID
重现代码:
data.frame(Date = as.Date(c("2018-06-02", "2018-07-05", "2018-08-02", "2019-04-15", "2019-05-15", "2019-05-30", "2019-06-12", "2019-06-27", "2018-02-15", "2018-04-10", "2018-06-12", "2018-08-13", "2018-08-27", "2017-03-09")),
Name = c(rep("Johan", 5), rep("Samantha", 3), rep("Mary", 5), "George"),
Item = c(rep("Apple", 5), rep("Orange", 3), rep("Lemon", 3), rep("Lime",2), "Kiwi"))
我想创建一个额外的列,为每门课程提供唯一标识符 - 即使用 stringi 或类似的。
理想情况下输出应该是这样的:
Date Name Item CourseID
1 2018-06-02 Johan Apple q3J
2 2018-07-05 Johan Apple q3J
3 2018-08-02 Johan Apple q3J
4 2019-04-15 Johan Apple f8j
5 2019-05-15 Johan Apple f8j
6 2019-05-30 Samantha Orange p8U
7 2019-06-12 Samantha Orange p8U
8 2019-06-27 Samantha Orange p8U
9 2018-02-15 Mary Lemon wi9
10 2018-04-10 Mary Lemon wi9
11 2018-06-12 Mary Lemon wi9
12 2018-08-13 Mary Lime q8U
13 2018-08-27 Mary Lime q8U
14 2017-03-09 George Kiwi jJ0
我试过使用 max/min 日期变量来解决这个问题,但是当我根据之前的购买模式识别中断时,我感到很困惑。
可能有一个我不知道哪个包有这方面的东西,但是到目前为止我一直在尝试使用 Tidyverse。
这是一种 dplyr 方法,它计算每个 Name/Item 组内的差距和滚动平均差距,然后标记较大的差距,并为每个较大的差距或名称或项目的变化分配一个新组。
df1 %>%
group_by(Name,Item) %>%
mutate(purch_num = row_number(),
time_since_first = Date - first(Date),
gap = Date - lag(Date, default = as.Date(-Inf)),
avg_gap = time_since_first / (purch_num-1),
new_grp_flag = gap > 180 | gap > 3*avg_gap) %>%
ungroup() %>%
mutate(group = cumsum(new_grp_flag))
当相同的变量以固定的日期间隔出现时,我试图将我的数据框的行分组到“课程”中。当时间频率出现差距或其中一个变量发生变化时,我想给它一个新的课程 ID。
举个例子,我的数据是这样的:
Date Name Item
1 2018-06-02 Johan Apple
2 2018-07-05 Johan Apple
3 2018-08-02 Johan Apple
4 2019-04-15 Johan Apple
5 2019-05-15 Johan Apple
6 2019-05-30 Samantha Orange
7 2019-06-12 Samantha Orange
8 2019-06-27 Samantha Orange
9 2018-02-15 Mary Lemon
10 2018-04-10 Mary Lemon
11 2018-06-12 Mary Lemon
12 2018-08-13 Mary Lime
13 2018-08-27 Mary Lime
14 2017-03-09 George Kiwi
Name
和 Item
的每个不同组合都应该生成一个新的课程 ID。
但是(棘手的部分)如果两个交易之间存在显着的时间差距,而其他变量是常数,则定义为:超过 6月 或 对于 Item
和 Name
那么应该给它一个新的 CourseID
在我的例子中:
- 因为 Johan 在 2018 年 8 月之后休息,之后的交易应该有一个新的
CourseID
。理想情况下,检查未来休息时间的间隔将基于这个新组的平均值。 - 萨曼莎每两周购买一次橙子,没有明显的缺口,因此她的所有交易都会有一个
CourseID
。 - Mary 定期购买柠檬,但随后转为定期购买酸橙,因此这些有两个
CourseID
s。 - George 刚买了一个 Kiwi,所以一个
CourseID
重现代码:
data.frame(Date = as.Date(c("2018-06-02", "2018-07-05", "2018-08-02", "2019-04-15", "2019-05-15", "2019-05-30", "2019-06-12", "2019-06-27", "2018-02-15", "2018-04-10", "2018-06-12", "2018-08-13", "2018-08-27", "2017-03-09")),
Name = c(rep("Johan", 5), rep("Samantha", 3), rep("Mary", 5), "George"),
Item = c(rep("Apple", 5), rep("Orange", 3), rep("Lemon", 3), rep("Lime",2), "Kiwi"))
我想创建一个额外的列,为每门课程提供唯一标识符 - 即使用 stringi 或类似的。
理想情况下输出应该是这样的:
Date Name Item CourseID
1 2018-06-02 Johan Apple q3J
2 2018-07-05 Johan Apple q3J
3 2018-08-02 Johan Apple q3J
4 2019-04-15 Johan Apple f8j
5 2019-05-15 Johan Apple f8j
6 2019-05-30 Samantha Orange p8U
7 2019-06-12 Samantha Orange p8U
8 2019-06-27 Samantha Orange p8U
9 2018-02-15 Mary Lemon wi9
10 2018-04-10 Mary Lemon wi9
11 2018-06-12 Mary Lemon wi9
12 2018-08-13 Mary Lime q8U
13 2018-08-27 Mary Lime q8U
14 2017-03-09 George Kiwi jJ0
我试过使用 max/min 日期变量来解决这个问题,但是当我根据之前的购买模式识别中断时,我感到很困惑。
可能有一个我不知道哪个包有这方面的东西,但是到目前为止我一直在尝试使用 Tidyverse。
这是一种 dplyr 方法,它计算每个 Name/Item 组内的差距和滚动平均差距,然后标记较大的差距,并为每个较大的差距或名称或项目的变化分配一个新组。
df1 %>%
group_by(Name,Item) %>%
mutate(purch_num = row_number(),
time_since_first = Date - first(Date),
gap = Date - lag(Date, default = as.Date(-Inf)),
avg_gap = time_since_first / (purch_num-1),
new_grp_flag = gap > 180 | gap > 3*avg_gap) %>%
ungroup() %>%
mutate(group = cumsum(new_grp_flag))