在R中对分组海洋光剖面数据执行暗信号识别的问题
问题描述
我正在研究海洋下行光剖面,尝试实现文献中的“暗信号识别”流程:
- 数据按Profile分组,每个分组用Lillifors检验判断light值是否符合正态分布
- 若不符合,移除该组内最浅深度的点并重复检验,直到通过正态性检验
- 剩余点标记为'dark',被移除的点标记为'light'
编写测试代码后,针对单个profile测试的循环代码运行报错:
Error in UseMethod("mutate") :
no applicable method for 'mutate' applied to an object of class "logical"
测试代码如下:
library(nortest) library(dplyr) # test dataset profile = c(1) depth = seq(1,250,1) PAR = seq(10,1,along.with = depth) PAR <- log(PAR) # 模拟光随深度的指数变化 p1 <- data.frame(profile = profile, depth = depth, PAR = PAR) profile = c(2) p2 <- data.frame(profile = profile, depth = depth, PAR = PAR) data <- rbind(p1,p2) p1[ , 'signal'] = NA
单个profile测试的循环代码:
for (i in p1) { ltest <- lillie.test(p1$PAR) if (ltest$p.value < 0.01) { p1 <- mutate(p1$signal == "light") p1 <- filter(p1, depth != min(depth)) } else if (ltest$p.value > 0.01) { p1 <- mutate(p1$signal == "dark" ) } }
错误原因
mutate语法错误:mutate(p1$signal == "light")是错误用法,mutate要求第一个参数是数据框,后续是列名 = 值的赋值逻辑,你直接传入了逻辑向量,导致函数无法识别对象类型。- 循环逻辑错误:
for (i in p1)会遍历数据框的每一列,完全不符合需求;且每次移除最浅点后,没有用剩余数据重新检验,而是一直基于原始数据判断。 - 标记逻辑错误:你直接过滤掉了要标记为"light"的点,丢失了这些点的标记信息,正确逻辑应该是保留所有点并分别标记。
修正后的代码
单个Profile的处理逻辑
library(nortest) library(dplyr) # 复制原始数据,避免修改原数据 p1_processed <- p1 %>% mutate(signal = NA_character_) # 循环进行Lillifors检验,直到通过或只剩一个点 while(nrow(p1_processed) > 1) { # 取当前未标记的数据做检验 current_par <- p1_processed$PAR[is.na(p1_processed$signal)] ltest <- lillie.test(current_par) if(ltest$p.value >= 0.01) { # 通过检验,剩余未标记点标记为dark p1_processed <- p1_processed %>% mutate(signal = ifelse(is.na(signal), "dark", signal)) break } else { # 未通过,找到当前未标记数据中最浅的深度,标记为light min_depth <- min(p1_processed$depth[is.na(p1_processed$signal)]) p1_processed <- p1_processed %>% mutate(signal = ifelse(depth == min_depth & is.na(signal), "light", signal)) } } # 处理只剩最后一个点的情况 if(nrow(p1_processed) == 1 && is.na(p1_processed$signal)) { p1_processed$signal <- "dark" }
多Profile批量处理
把单个Profile的逻辑封装成函数,用group_modify实现分组批量处理:
# 定义单个分组的处理函数 process_profile <- function(df) { df <- df %>% mutate(signal = NA_character_) while(nrow(df) > 1) { current_par <- df$PAR[is.na(df$signal)] ltest <- lillie.test(current_par) if(ltest$p.value >= 0.01) { df <- df %>% mutate(signal = ifelse(is.na(signal), "dark", signal)) break } else { min_depth <- min(df$depth[is.na(df$signal)]) df <- df %>% mutate(signal = ifelse(depth == min_depth & is.na(signal), "light", signal)) } } if(nrow(df) == 1 && is.na(df$signal)) { df$signal <- "dark" } return(df) } # 对所有Profile分组处理 data_processed <- data %>% group_by(profile) %>% group_modify(~process_profile(.x)) %>% ungroup()
内容的提问来源于stack exchange,提问作者amazing_zebra
相关产品推荐
相关产品推荐

