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

如何在R中基于分组从不同DataFrame取值实现数据归一化?

问题描述

我有如下结构的DataFrame:

Col1 = c("A1", "A1", "A2", "A2")
Col2 = c("B1", "B1", "B2", "B2")
Value = c(10, 20, 30, 40)
df = data.frame(Col1, Col2, Value)

该DataFrame包含多组观测数据,有两个因子列(Col1、Col2)和一个数值列(Value),同一分组对应多行不同数值,且我有多个类似结构的DataFrame。

另外还有两个存储所有分组(Col1和Col2)全局最小、最大值的DataFrame:

MinCol1 = c("A1", "A2")
MinCol2 = c("B1", "B2")
MinValue = c(1, 1)
mins = data.frame(MinCol1, MinCol2, MinValue)

MaxCol1 = c("A1", "A2")
MaxCol2 = c("B1", "B2")
MaxValue = c(100, 100)
maxes = data.frame(MaxCol1, MaxCol2, MaxValue)

我需要对这类DataFrame按分组进行数值归一化,将Value映射到[0,1]区间,且归一化的取值范围要从上述mins和maxes中获取对应分组的最小值和最大值。

我写了如下函数,但不确定range(...)里该填什么,才能实现按分组从mins和maxes中查找对应范围:

normalizeDataForAllBenchmarks = function(df, mins, maxes) {
    
    ### Normalize metrics [0,1]
    df_normal = df %>%
      group_by(Process, Category, Metric) %>%
      mutate(Value = rescale(Value, to = c(0,1), from = range(...)))
    
    return(df_normal)
}
解决方案

注:你函数中的分组列Process, Category, Metric与示例中的Col1, Col2对应,以下示例将用Col1和Col2作为分组列,你可根据实际场景替换为自己的分组列名。

方法一:合并全局最值后计算归一化

这种方法逻辑直观,先合并全局最值表,再与目标DataFrame关联,最后直接用对应分组的全局极值计算归一化:

library(dplyr)
library(scales)

normalizeDataForAllBenchmarks = function(df, mins, maxes) {
    # 重命名最值表列名,方便后续合并
    mins_renamed = mins %>% 
        rename(Col1 = MinCol1, Col2 = MinCol2, global_min = MinValue)
    maxes_renamed = maxes %>% 
        rename(Col1 = MaxCol1, Col2 = MaxCol2, global_max = MaxValue)
    
    # 合并全局最小值和最大值表
    global_ranges = mins_renamed %>%
        inner_join(maxes_renamed, by = c("Col1", "Col2"))
    
    # 关联目标表并计算归一化,最后移除临时列
    df_normal = df %>%
        inner_join(global_ranges, by = c("Col1", "Col2")) %>%
        mutate(Value = rescale(Value, to = c(0,1), from = c(global_min, global_max))) %>%
        select(-global_min, -global_max)
    
    return(df_normal)
}

方法二:分组内匹配全局最值

如果想保留group_by的写法,可在分组内根据当前分组的标识,从最值表中提取对应极值:

library(dplyr)
library(scales)

normalizeDataForAllBenchmarks = function(df, mins, maxes) {
    df_normal = df %>%
        group_by(Col1, Col2) %>%  # 替换为你的实际分组列:Process, Category, Metric
        mutate(
            # 提取当前分组的全局最小值
            global_min = mins$MinValue[mins$MinCol1 == first(Col1) & mins$MinCol2 == first(Col2)],
            # 提取当前分组的全局最大值
            global_max = maxes$MaxValue[maxes$MaxCol1 == first(Col1) & maxes$MaxCol2 == first(Col2)],
            # 计算归一化值
            Value = rescale(Value, to = c(0,1), from = c(global_min, global_max))
        ) %>%
        select(-global_min, -global_max) %>%
        ungroup()
    
    return(df_normal)
}

测试验证

用你提供的示例数据调用函数:

result = normalizeDataForAllBenchmarks(df, mins, maxes)
print(result)

输出结果符合预期:

Col1 Col2      Value
1   A1   B1 0.09090909
2   A1   B1 0.19191919
3   A2   B2 0.29292929
4   A2   B2 0.39393939

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 21:37:43