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

如何在R中按行(观测值)将数据归一化至[-1:1]区间?

按行将数据归一化到[-1,1]区间的实现方案

Got it, you're looking to normalize your data row-wise (per observation) to the [-1, 1] range—similar to z-score but focused on each row's own distribution, so you can plot them together in a boxplot and compare their patterns. Let's walk through how to do this with your sample data.

核心公式说明

要将一行内的数值映射到[-1,1],我们可以用这个线性缩放公式:

scaled_value = 2 * (x - row_min) / (row_max - row_min) - 1

逻辑很简单:先把行内数据缩放到[0,1]区间,再平移拉伸到[-1,1]。其中row_min是当前行的最小值,row_max是当前行的最大值。

方法1:用dplyr实现(直观易读)

我们可以结合rowwise()和across()来对每行数据做处理,步骤清晰,适合大多数场景:

library(dplyr)
library(tidyr)
library(ggplot2)

# 你的原始数据
Obs <- c("A", "B", "C")
count1 <- c(100,15,3)
count2 <- c(250, 30, 5)
count3 <- c(290, 20, 8)
count4<- c(80,12, 2 )
df <- data.frame(Obs, count1, count2, count3, count4)

# 按行执行归一化
df_scaled <- df %>%
  rowwise() %>%
  # 计算每行的最小值和最大值
  mutate(
    row_min = min(c_across(starts_with("count"))),
    row_max = max(c_across(starts_with("count")))
  ) %>%
  # 对所有count列应用归一化公式,生成带前缀的新列
  mutate(
    across(starts_with("count"), 
           ~ 2 * (.x - row_min)/(row_max - row_min) - 1,
           .names = "scaled_{.col}")
  ) %>%
  ungroup() %>%
  # 移除中间计算的辅助列(可选)
  select(-row_min, -row_max)

# 转换为长格式用于绘图
dff_scaled <- df_scaled %>%
  pivot_longer(cols = starts_with("scaled_"), 
               names_to = "count", 
               values_to = "Scaled_Value") %>%
  # 去掉scaled_前缀,让x轴标签和原始数据一致
  mutate(count = gsub("scaled_", "", count))

# 绘制箱线图+散点
ggplot(dff_scaled, aes(x = count, y = Scaled_Value)) +
  geom_jitter(alpha = 0.1, color = "tomato") +
  geom_boxplot(fill = "lightblue", alpha = 0.5) +
  ylim(-1, 1) + # 强制显示[-1,1]区间
  labs(title = "Row-wise Normalized Data (-1 to 1)", 
       y = "Scaled Value")

方法2:用矩阵操作实现(高效处理大数据)

如果你的数据集非常大,rowwise()的效率可能不够高,这时可以用矩阵运算来加速:

# 提取数值列转为矩阵
count_matrix <- as.matrix(df[, -1])
# 计算每行的最小值和最大值
row_mins <- apply(count_matrix, 1, min)
row_maxs <- apply(count_matrix, 1, max)
# 广播计算归一化值(R会自动处理维度匹配)
scaled_matrix <- 2 * (count_matrix - row_mins)/(row_maxs - row_mins) - 1
# 转换回dataframe并合并Obs列
df_scaled_matrix <- cbind(df[, 1], as.data.frame(scaled_matrix))
colnames(df_scaled_matrix)[-1] <- paste0("scaled_", colnames(count_matrix))

# 后续绘图步骤和方法1完全一致
dff_scaled_matrix <- df_scaled_matrix %>%
  pivot_longer(cols = starts_with("scaled_"), 
               names_to = "count", 
               values_to = "Scaled_Value") %>%
  mutate(count = gsub("scaled_", "", count))

ggplot(dff_scaled_matrix, aes(x = count, y = Scaled_Value)) +
  geom_jitter(alpha = 0.1, color = "tomato") +
  geom_boxplot(fill = "lightblue", alpha = 0.5) +
  ylim(-1, 1) +
  labs(title = "Row-wise Normalized Data (Matrix Method)", 
       y = "Scaled Value")

效果说明

经过行级归一化后,每个观测值(A/B/C)的数值都会被映射到[-1,1]区间:

  • 该行的最小值会变成-1
  • 该行的最大值会变成1
  • 中间值按线性比例分布

这样你就能在同一个箱线图中清晰对比不同观测值在count1-count4上的模式差异了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:19:45