如何使用R按表头条件统一数据列的度量单位?
统一多组不同单位数据的R实现方案
问题背景
给定的df1包含NY、PR、KR三组记录,每组前有一行定义该组各列的度量单位,需要将所有列统一到指定标准单位:
- 容量类(Beer、Coffee、Gasoline、Milk):统一为liters
- 面积类(Warehouse):统一为square feet
- 距离类(Nearest place):统一为miles
已知转换系数:
- 1 gallon = 3.78541 liters
- 1 pint = 0.473176 liters
- 1 oz = 0.0295735 liters
- 11 square feet = 1.02193 square meters → 1 square meter ≈ 10.7639 square feet
- 1 mile = 1.60934 kilometers → 1 kilometer ≈ 0.621371 miles
优雅实现方案
使用tidyverse工具链完成分组识别、单位提取、数值转换和数据合并,代码可读性强且易于扩展:
library(tidyverse) # 1. 定义单位转换规则:键为(度量类型, 当前单位),值为转换到目标单位的系数 conversion_rules <- list( # 容量类目标:liters c("Beer", "pints") = 0.473176, c("Beer", "liters") = 1, c("Coffee", "oz") = 0.0295735, c("Coffee", "cups (120 ml)") = 0.12, # 120ml = 0.12 liters c("Gasoline", "galons") = 3.78541, c("Gasoline", "liters") = 1, c("Milk", "galons") = 3.78541, c("Milk", "liters") = 1, # 面积类目标:square feet c("Warehouse", "square feet") = 1, c("Warehouse", "square meters") = 11 / 1.02193, # 距离类目标:miles c("Nearest place", "miles") = 1, c("Nearest place", "kilometers") = 1 / 1.60934 ) # 2. 处理原始数据:添加组标识,拆分单位行和数据行 processed_df <- df1 %>% mutate(group_id = cumsum(M1 == "M1")) %>% group_by(group_id) %>% group_split() %>% map_dfr(function(group) { # 提取单位行(每组第一行) unit_row <- slice(group, 1) # 提取数据行(每组剩余行)并转数值类型 data_rows <- slice(group, -1) %>% mutate(across(-c(M1, M2), as.numeric)) # 提取每个列的度量类型和当前单位 col_info <- names(data_rows) %>% setdiff(c("M1", "M2")) %>% map_dfr(function(col) { metric_type <- str_extract(col, "^[^,]+") current_unit <- unit_row[[col]] tibble(col_name = col, metric_type, current_unit) }) # 对每个数值列应用单位转换并重命名列 converted_data <- data_rows %>% mutate(across(-c(M1, M2), function(col_val, col_name) { info <- filter(col_info, col_name == !!col_name) conv_coeff <- conversion_rules[[c(info$metric_type, info$current_unit)]] col_val * conv_coeff }, .names = "{str_extract(.col, '^[^,]+')}")) %>% rename_with(function(nm) { case_when( str_detect(nm, "Beer|Coffee|Gasoline|Milk") ~ paste0(nm, "_liters"), str_detect(nm, "Warehouse") ~ paste0(nm, "_sqft"), str_detect(nm, "Nearest place") ~ paste0(nm, "_miles") ) }) converted_data }) # 查看最终结果 print(processed_df)
代码说明
- 转换规则定义:用列表存储(度量类型, 当前单位)到转换系数的映射,新增单位时只需扩展此列表,维护成本低。
- 分组处理:通过
cumsum(M1 == "M1")自动识别每组的起始行,将数据拆分为独立组后逐个处理,避免跨组干扰。 - 单位提取与转换:从单位行中提取每个列的当前单位,匹配转换规则后完成数值转换,同时重命名列以明确标准单位。
- 数据合并:用
map_dfr将所有转换后的组合并为最终整洁数据框,保留原始分组的标识列(M1、M2)。
内容的提问来源于stack exchange,提问作者Alexander Shemetev
相关产品推荐
相关产品推荐

