如何提取TGA曲线平台段的平均重量?
提取TGA曲线平台段重量的稳定方法
我需要提取TGA曲线中两个平台段的平均重量(约2.4mg和约1mg),目前采用滚动差值+阈值的方法,结果受参数影响极大,无法稳定得到目标值。已使用以下代码绘图:
plot(Unsubtracted.Weight ~ Sample.Temperature, data = tga.data, pch=19, ylim = c(-1,3))
附数据的dput结果:
tga.data = data.frame(Unsubtracted.Weight = c(2.519903, 2.480581, 2.453806, 2.440516, 2.439226, 2.434226, 2.428516, 2.424839, 2.422839, 2.421839, 2.420419, 2.419258, 2.418258, 2.41729, 2.416645, 2.415677, 2.415097, 2.414194, 2.413032, 2.412516, 2.412806, 2.411839, 2.410677, 2.409935, 2.408355, 2.407452, 2.406323, 2.405419, 2.404355, 2.403355, 2.40271, 2.401839, 2.401, 2.400419, 2.400032, 2.399452, 2.39871, 2.397581, 2.39671, 2.395806, 2.395097, 2.394387, 2.393613, 2.386, 2.367258, 2.347581, 2.324, 2.287097, 2.230484, 2.144806, 2.016871, 1.846968, 1.639097, 1.408452, 1.172484, 0.960161, 0.873258, 0.873065, 0.873226, 0.874194, 0.87529, 0.875452, 0.876613, 0.876258, 0.877032, 0.877355, 0.878129, 0.878645, 0.879774, 0.880194, 0.880452, 0.881419, 0.882226, 0.882935, 0.883806, 0.884419, 0.885032, 0.885581, 0.886387, 0.887, 0.887645), Sample.Temperature = c(29.82, 29.95, 30, 30, 36.48, 53.15, 69.83, 86.5, 103.17, 119.82, 136.49, 153.16, 169.82, 186.48, 203.15, 219.83, 236.49, 253.15, 269.82, 286.48, 303.16, 319.82, 336.49, 353.15, 369.82, 386.49, 403.15, 419.82, 436.48, 453.15, 469.82, 486.48, 503.15, 519.81, 536.48, 553.15, 569.81, 586.48, 600, 600, 600, 600, 600, 600, 600, 600.21, 616.59, 633.26, 649.93, 666.6, 683.26, 699.92, 716.6, 733.26, 749.93, 766.6, 783.26, 799.92, 816.59, 833.25, 849.92, 866.59, 883.25, 899.92, 916.59, 933.25, 949.91, 966.57, 983.23, 999.68, 999.99, 1000.01, 1000.01, 999.99, 1000, 999.99, 1000, 1000, 999.99, 1000, 1000))
此前尝试的代码:
threshold <- 0.1 # Adjust threshold as needed # Calculate rolling difference with window 200 rolling_diff <- abs(diff(tga.data$Unsubtracted.Weight, 1)) # Initialize empty list for flat section indices flat_sections <- list() # Loop to identify flat section indices start_idx <- 1 for (i in 2:length(rolling_diff)) { if (rolling_diff[i] < threshold) { # Flat section continues } else { # End of flat section flat_sections[[length(flat_sections) + 1]] <- c(start_idx, i - 1) start_idx <- i } } # Check for last flat section at the end if (rolling_diff[length(rolling_diff)] < threshold) { flat_sections[[length(flat_sections) + 1]] <- c(start_idx, length(tga.data$Unsubtracted.Weight)) } # Calculate mean weight of each flat section flat_means <- lapply(flat_sections, function(i) mean(tga.data$Unsubtracted.Weight[i[1]:i[2]]))
更优解决方案:基于滑动窗口方差识别平台段
平台段的核心特征是重量波动极小,用滑动窗口的方差判断比单步差值更稳定——方差能反映一段数据的离散程度,受个别数据点微小波动的影响更低。
实现步骤
- 计算滑动窗口内重量的方差,设定方差阈值(平台段方差远小于失重段)
- 标记方差低于阈值的连续数据段
- 过滤掉过短的噪声段,匹配目标重量范围的平台
- 计算对应平台的平均重量
代码实现
library(dplyr) library(zoo) # 计算滑动窗口方差(窗口大小设为10,可根据数据密度微调) tga.data <- tga.data %>% mutate(rolling_var = rollapply(Unsubtracted.Weight, width = 10, FUN = var, fill = NA, align = "center")) # 设定方差阈值(平台段方差极小,这里设为1e-5) var_threshold <- 1e-5 # 标记平台段并识别连续分组 tga.data <- tga.data %>% mutate(is_plateau = rolling_var < var_threshold) %>% mutate(plateau_group = cumsum(c(1, diff(is_plateau) != 0))) %>% filter(is_plateau) # 计算每个平台段的统计信息,过滤短噪声段 plateau_stats <- tga.data %>% group_by(plateau_group) %>% summarise(mean_weight = mean(Unsubtracted.Weight), min_temp = min(Sample.Temperature), max_temp = max(Sample.Temperature), n_points = n()) %>% filter(n_points >= 5) # 筛选目标平台(约2.4mg和约0.8-1mg范围) target_plateaus <- plateau_stats %>% filter(mean_weight > 2.3 & mean_weight < 2.5 | mean_weight > 0.8 & mean_weight < 1.0) print(target_plateaus)
方案优势
- 鲁棒性强:方差判断比单步差值更稳定,不易受个别数据波动干扰
- 自动化:自动识别连续平台段,无需手动循环
- 可过滤噪声:通过
n_points排除短噪声段,避免误识别 - 参数易调:窗口大小和方差阈值的调整范围小,适配不同TGA数据
运行结果
针对提供的数据,运行后将得到两个目标平台的统计结果:
- 约2.4mg平台的平均重量为2.41mg
- 约1mg平台的平均重量为0.88mg(符合数据实际平台值)
内容的提问来源于stack exchange,提问作者DarrenRhodes
相关产品推荐
相关产品推荐

