高效的 R 代码,根据同一数据帧中的相关行为数据帧中的每一行分配时间戳(年份)

问题描述 投票:0回答:1

我有一个客户交易数据集,需要基于一组相当复杂的“时间”规则创建一个新列(Vintage):

  • 简而言之,要求是按名称出现在书中的日期标记每个条目(行)(即它们何时是“新”“运动”)。在实际应用中,有几种情况需要考虑:

  • 如果名称首次出现在带有“EXISTING”标签的数据集中,则 Vintage = 'Back Book'

  • 如果相同名称在稍后的报告日期有“新”标签 - 年份将成为“新”条目的日期

  • 对于“新”标签后面的“现有”条目 - 年份 = 最近的“新”条目日期

  • 如果该名称有新的“NEW”条目,则 Vintage 值将成为新“NEW”条目的日期

这可能听起来很复杂,所以我添加了下图来说明所有可能情况下的预期结果:

enter image description here

重新创建玩具数据集的代码:

structure(list(Date = c(20240430L, 20240531L, 20240630L, 20240229L, 
20240331L, 20240531L, 20240630L, 20240731L, 20230930L, 20231031L, 
20231231L, 20230930L, 20231031L, 20231231L, 20240531L, 20240731L
), Name = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 
3L, 4L, 4L, 4L, 4L, 4L), .Label = c("A", "B", "C", "D"), class = "factor"), 
    Movement = structure(c(1L, 1L, 1L, 1L, 1L, 2L, 1L, 1L, 2L, 
    1L, 1L, 1L, 1L, 2L, 1L, 2L), .Label = c("EXISTING", "NEW"
    ), class = "factor"), Vintage = structure(c(5L, 5L, 5L, 5L, 
    5L, 3L, 3L, 3L, 1L, 1L, 1L, 5L, 5L, 2L, 2L, 4L), .Label = c("20230930", 
    "20231231", "20240531", "20240731", "Back Book"), class = "factor")), class = "data.frame", row.names = c(NA, 
-16L))

我正在寻找一个可以有效地创建“Vintage”列的代码,因为数据集有超过 100k 条目并且不断增长。谢谢!

我尝试创建数据集的两个副本(df_A,df_B),并使用 rowwise()、mutate() 和从 mutate() 内调用的自定义“assignVintage”函数从 df_A 到 df_B 查找每一行的 Vintage ,但是代码只执行所需时间规则的子集,尽管效率仍然非常低,运行时间超过 20 分钟 - 这就是为什么我正在寻找一种更优雅的解决方案(如果存在)。

r dataframe dplyr mutate
1个回答
0
投票

这是一个解决方案。

  • 创建一个辅助列,告知它是否是组的开头,其中
    Movement
    "NEW"
    ;
  • 如果不是因为组还没有开始,则分配
    "Back Book"
    ,如果是并且是组的第一个元素,则分配日期,否则分配
    NA
    ;
  • 用之前的值填充
    NA
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union

df1 %>%
  mutate(new = cumsum(Movement == "NEW"), .by = Name) %>%
  mutate(
    Vintage2 = case_when(
      new == 0 ~ "Back Book", 
      new > 0 & Movement == "NEW" ~ as.character(Date),
      TRUE ~ NA_character_
    ), 
    .by = new
  ) %>%
  tidyr::fill(Vintage2) %>%
  select(-new)
#>        Date Name Movement   Vintage  Vintage2
#> 1  20240430    A EXISTING Back Book Back Book
#> 2  20240531    A EXISTING Back Book Back Book
#> 3  20240630    A EXISTING Back Book Back Book
#> 4  20240229    B EXISTING Back Book Back Book
#> 5  20240331    B EXISTING Back Book Back Book
#> 6  20240531    B      NEW  20240531  20240531
#> 7  20240630    B EXISTING  20240531  20240531
#> 8  20240731    B EXISTING  20240531  20240531
#> 9  20230930    C      NEW  20230930  20230930
#> 10 20231031    C EXISTING  20230930  20230930
#> 11 20231231    C EXISTING  20230930  20230930
#> 12 20230930    D EXISTING Back Book Back Book
#> 13 20231031    D EXISTING Back Book Back Book
#> 14 20231231    D      NEW  20231231  20231231
#> 15 20240531    D EXISTING  20231231  20231231
#> 16 20240731    D      NEW  20240731  20240731

创建于 2024-08-21,使用 reprex v2.1.0

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.