You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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)

代码说明

  1. 转换规则定义:用列表存储(度量类型, 当前单位)到转换系数的映射,新增单位时只需扩展此列表,维护成本低。
  2. 分组处理:通过cumsum(M1 == "M1")自动识别每组的起始行,将数据拆分为独立组后逐个处理,避免跨组干扰。
  3. 单位提取与转换:从单位行中提取每个列的当前单位,匹配转换规则后完成数值转换,同时重命名列以明确标准单位。
  4. 数据合并:用map_dfr将所有转换后的组合并为最终整洁数据框,保留原始分组的标识列(M1、M2)。

内容的提问来源于stack exchange,提问作者Alexander Shemetev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 19:45:39