在循环中使用 Mutate 和 Case_when 时的问题

Posted

技术标签:

【中文标题】在循环中使用 Mutate 和 Case_when 时的问题【英文标题】:Issue when using Mutate and Case_when in a loop 【发布时间】:2022-01-12 15:56:30 【问题描述】:

我有一个数据框,其中包含当天 (lg) 来自赛艇的所有信息,我希望创建一个变量来告诉我游艇参加的比赛。这场比赛的开始和结束时间在单独的 df (种族信息)。我可以按比赛时间进行过滤,但每天比赛的数量是可变的,所以它可能需要一个循环。

一些数据

lg <- structure(list(Date = structure(c(18897, 18897, 18897, 18897, 
18897, 18897, 18897, 18897, 18897, 18897), class = "Date"), Time = structure(c(1632725883, 
1632725884, 1632725885, 1632725886, 1632725887, 1632725888, 1632725889, 
1632725890, 1632725891, 1632725892), tzone = "", class = c("POSIXct", 
"POSIXt")), Lat = c(43.2760531, 43.276059, 43.276065, 43.2760708, 
43.2760766, 43.2760858, 43.276095, 43.2761, 43.276105, 43.2761095
), Lon = c(6.619109, 6.619136, 6.619163, 6.6191932, 6.6192235, 
6.6192488, 6.619274, 6.6192988, 6.6193235, 6.6193532), Awa = c(-7.1, 
-7.12, -7.15, -6.57, -6, -6.2, -6.4, -5.28, -4.15, 0.25), X = 1:10), row.names = c(NA, 
-10L), class = "data.frame")

这是游艇上的数据。

更多数据

RaceInfo <- structure(list(date = structure(c(18897, 18896), class = "Date"), 
    RaceStartTime = structure(c(1632738480, 1632751560), tzone = "", class = c("POSIXct", 
    "POSIXt")), RaceNum = c("1", "2"), RaceFinishTime = structure(c(1632751520, 
    1632753000), tzone = "", class = c("POSIXct", "POSIXt"))), row.names = c("event.2", 
"1"), class = "data.frame")

在 RaceInfo df 中,它告诉我们每场比赛的开始和结束时间,如前所述,可能有很多比赛,我需要根据RaceInfo df。

我的关闭尝试是这样的,但循环是我游戏中的一个弱点。

for (i in RaceInfo$RaceNum)
      
      lg <- lg %>%
        mutate(Racenum = case_when(
          lg$Time >= (subset(RaceInfo$RaceStartTime, RaceInfo$RaceNum == i)) &
            lg$Time <= (subset(RaceInfo$RaceFinishTime, RaceInfo$RaceNum  == i)) ~ i))
      
    


但这只会返回循环中的最后一个数字

【问题讨论】:

请修正您的数据。 –&gt; 是错误的赋值运算符(你想要&lt;-),但更重要的是,第二个dput 输出不完整。我认为您可以只使用 data.table 非等连接或foverlaps 考虑merge(交叉连接)+subset如果数据相对较小到中等大小:lg &lt;- merge(lg, RaceInfo, by=NULL) |&gt; subset(Date &gt;= RaceStartTime &amp; Date &lt;= RaceEndTime) 已删除。我不想特别合并数据集,除非它是唯一的方法。只是希望在lg 中创建一个新变量。我确信这是可能的并且使用合并更快,但你的回答并没有给我我想要的结果。你能帮我进一步吗?再次感谢 哎呀!如果将Date 调整为Time 并将RaceEndTime 调整为RaceFinishTime 会怎样? 您的示例数据没有用,因为显然这艘船不在两场比赛中的一场。我相信您应该进行非 equi 连接。 【参考方案1】:

mutatecase_when 方法实际上是在数据框中分配计算列,而不是专门用于子集数据框本身。

相反,考虑dplyr::filter(类似于base::subset)甚至dplyr::between,并收集您的迭代结果以构建数据框列表。然后,rbind 最终结果。要按唯一值进行子集化,请参阅by

df_list <- lapply(RaceInfo$RaceNum, function(i)      
      dplyr::filter(
          lg,
          dplyr::between(
              Time,
              RaceInfo$StartTime[RaceInfo$Racenum == i],
              RaceInfo$RaceFinishTime[RaceInfo$Racenum == i]
          )
      )
)

final_df <- dplyr::bind_rows(df_list)

但如上所述,如果您的数据可以通过一组不同的 RaceInfo 进行管理,请考虑使用过滤器进行交叉连接:

final_df <- dplyr::full_join(lg, RaceInfo, by = character()) %>%
    filter(lg, between(
                 Time,
                 RaceInfo$StartTime[RaceInfo$Racenum == i],
                 RaceInfo$RaceFinishTime[RaceInfo$Racenum == i]
               )
    )

【讨论】:

以上是关于在循环中使用 Mutate 和 Case_when 时的问题的主要内容,如果未能解决你的问题,请参考以下文章

R语言dplyr包使用case_when函数和mutate函数生成新的数据列实战:基于单列生成新的数据列基于多列生成新的数据列

Sparklyr 使用 case_when 和变量

如何在自定义函数中使用 mutate 创建新列

dplyr case_when具有动态案例数时

如何从 dplyr 中的 case_when 捕获逻辑

自动递增到 case_when 或替换循环