如何简化计算度假屋公寓价格的冗长R代码?
简化R代码:用查找表替代冗长的case_when
你的代码核心是根据区域、年份、季节三个维度匹配价格,这种多维度规则最适合用**查找表(Lookup Table)**实现,不仅代码更简洁,后续修改价格、新增年份/区域也更方便。
步骤1:创建价格规则查找表
先把所有价格规则整理成一个数据框,每个规则一行,清晰明了:
library(tidyverse) price_lookup <- tribble( ~region, ~year, ~season, ~price_night, "ost", 2018, "hochsaison", 180, "ost", 2018, "mittelsaison",160, "ost", 2018, "nebensaison", 140, "west", 2018, "hochsaison", 180, "west", 2018, "mittelsaison",160, "west", 2018, "nebensaison", 140, "sued", 2018, "hochsaison", 100, "sued", 2018, "mittelsaison",80, "sued", 2018, "nebensaison", 60, "ost.west", 2018, "hochsaison", 360, "ost.west", 2018, "mittelsaison",320, "ost.west", 2018, "nebensaison", 280, "sued.ost", 2018, "hochsaison", 280, "sued.ost", 2018, "mittelsaison",240, "sued.ost", 2018, "nebensaison", 200, "sued.west", 2018, "hochsaison", 280, "sued.west", 2018, "mittelsaison",240, "sued.west", 2018, "nebensaison", 200, "gesamtes_haus",2018, "hochsaison", 460, "gesamtes_haus",2018, "mittelsaison",400, "gesamtes_haus",2018, "nebensaison", 340, "ost", 2022, "hochsaison", 240, "ost", 2022, "mittelsaison",210, "ost", 2022, "nebensaison", 170, "west", 2022, "hochsaison", 240, "west", 2022, "mittelsaison",210, "west", 2022, "nebensaison", 170, "sued", 2022, "hochsaison", 120, "sued", 2022, "mittelsaison",100, "sued", 2022, "nebensaison", 80, "ost.west", 2022, "hochsaison", 480, "ost.west", 2022, "mittelsaison",420, "ost.west", 2022, "nebensaison", 340, "sued.ost", 2022, "hochsaison", 360, "sued.ost", 2022, "mittelsaison",310, "sued.ost", 2022, "nebensaison", 250, "sued.west", 2022, "hochsaison", 360, "sued.west", 2022, "mittelsaison",310, "sued.west", 2022, "nebensaison", 250, "gesamtes_haus",2022, "hochsaison", 600, "gesamtes_haus",2022, "mittelsaison",520, "gesamtes_haus",2022, "nebensaison", 420 )
步骤2:转换原数据格式
原数据中,区域(ost/west等)和季节(hochsaison等)都是宽格式(每个类别一列),需要转成长格式才能和查找表匹配:
ue_processed <- ue %>% # 提取当前行对应的有效区域(仅保留值>0的区域) pivot_longer(cols = c(ost, west, sued, ost.west, sued.ost, sued.west, gesamtes_haus), names_to = "region", values_to = "region_val") %>% filter(region_val > 0) %>% select(-region_val) %>% # 提取当前行对应的有效季节(仅保留值>0的季节) pivot_longer(cols = c(hochsaison, mittelsaison, nebensaison), names_to = "season", values_to = "season_val") %>% filter(season_val > 0) %>% select(-season_val)
步骤3:匹配价格并合并回原数据
把处理后的数据和查找表合并,得到对应价格,再合并回原数据:
ue <- ue %>% left_join( ue_processed %>% left_join(price_lookup, by = c("region", "year", "season")), by = names(ue)[!names(ue) %in% c("region", "season")] ) %>% # 处理无匹配规则的情况,默认价格为0 mutate(price_night = replace_na(price_night, 0))
为什么这样更好?
- 可读性强:查找表集中展示所有规则,一眼就能看懂各维度对应的价格
- 易维护:新增年份、区域或修改价格,直接修改查找表即可,无需改动主逻辑
- 减少错误:避免重复编写case_when条件时出现的语法疏漏(比如你原代码中2018年最后一个条件后缺失逗号)
内容的提问来源于stack exchange,提问作者Sofia
相关产品推荐
相关产品推荐

