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