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

求助:为多站点数据框添加逐时间步P/PET/Q异常值列

问题排查与代码修正

原代码问题分析

  • 最终通过unlist(results)将嵌套列表转为长格式数据,完全偏离了“在原数据列后追加异常值列”的需求
  • 循环生成的结果仅存储了异常值,未与原数据对应拼接,也未维护原数据的列顺序

修正方案(两种实现方式)

方式1:使用tidyverse的宽转长/长转宽流程(简洁高效)

利用pivot_longer将数据转为长格式,按站点和参数分组计算异常值,再转回宽格式得到目标结果:

library(tidyverse)
library(lubridate)

# 保留用户提供的原数据df
df <- data.frame(
  stringsAsFactors = FALSE,
  check.names = FALSE,
  Date = c("01/11/1876","01/12/1876",
           "01/01/1877","01/02/1877","01/03/1877",
           "01/04/1877","01/05/1877","01/06/1877",
           "01/07/1877","01/08/1877","01/09/1877",
           "01/10/1877","01/11/1877","01/12/1877",
           "01/01/1878"),
  `Att-Bissen P [mm]` = c(48.5,111.2,29.7,139.4,90.1,25.9,
                          216,94.6,40.5,NA,64.4,68.8,44.7,
                          34.8,71.9),
  `Att-Bissen PET [mm]` = c(88.4,88.3,80.5,53.4,36.7,20.2,
                            21.6,21.7,21.3,37.6,46.1,66.5,89.8,
                            121.5,87.7),
  `Att-Bissen Q [mm]` = c(13.5,12.6,11.3,12.9,44.6,21.3,
                          194.9,NA,49.1,46.7,63.6,25.4,19.8,
                          15.3,16),
  `Rau. Merl P [mm]` = c(43.7,104.2,25.5,131.3,83.7,21.9,
                         205.2,88.1,35.9,61,59,63.2,40,
                         30.4,66.2),
  `Rau. Merl PET [mm]` = c(91.4,91.3,83.2,54.9,37.5,20.3,
                           21.8,21.8,21.4,38.4,47.3,68.6,NA,
                           125.9,90.7),
  `Rau. Merl Q [mm]` = c(8.7,10.6,8.4,14.3,23.7,14.1,
                         131.6,106.7,40.1,42.4,50.3,24.6,16.7,
                         11.3,13.7),
  `Syre Felsmuhle/Mertert P [mm]` = c(37.8,89.5,22.3,112.7,72,19.2,
                                      175.8,75.8,31.2,52.6,50.9,54.5,34.7,
                                      26.5,57.1),
  `Syre Felsmuhle/Mertert PET [mm]` = c(95.6,95.6,86.9,57.2,38.8,20.7,
                                        22.3,22.3,21.9,39.8,49.2,71.6,97.2,
                                        132,94.9),
  `Syre Felsmuhle/Mertert Q [mm]` = c(16,22,17.9,24,23.1,11.4,91,NA,
                                      NA,45.2,65.6,NA,NA,NA,NA),
  `Wiltz-Winseler P [mm]` = c(50.1,106.9,33,132.4,87.7,29.7,
                              201.8,91.8,42.8,66.4,64.5,68.5,46.7,
                              37.7,71.3),
  `Wiltz-Winseler PET [mm]` = c(87.4,87.3,79.5,52.5,35.8,19.4,
                                20.8,20.8,20.4,36.7,NA,NA,88.8,
                                120.4,86.7),
  `Wiltz-Winseler Q [mm]` = c(7.2,6.3,5,8.6,33.9,32.2,234.2,
                              148.1,68.5,51.5,101.4,25.7,18.7,
                              14.3,12.1))

# 宽转长,提取站点与参数信息
df_long <- df %>%
  pivot_longer(-Date, 
               names_to = c("Site", "Parameter"),
               names_pattern = "(.*) (P|PET|Q) \\[mm\\]",
               values_to = "Value")

# 分组计算异常值
df_anomaly <- df_long %>%
  group_by(Site, Parameter) %>%
  mutate(Anomaly = Value - mean(Value, na.rm = TRUE)) %>%
  ungroup()

# 转回宽格式,调整列顺序使原参数列与异常值列相邻
df_final <- df_anomaly %>%
  pivot_wider(names_from = Parameter,
              values_from = c(Value, Anomaly),
              names_glue = "{Site} {.value} {Parameter} [mm]") %>%
  select(Date, 
         starts_with("Att-Bissen"),
         starts_with("Rau. Merl"),
         starts_with("Syre Felsmuhle/Mertert"),
         starts_with("Wiltz-Winseler"))

方式2:修正原有循环逻辑

保留原循环结构,调整结果拼接方式,将异常值列插入到对应参数列之后:

library(tidyverse)
library(lubridate)

# 保留用户提供的原数据df和formula_1函数
df <- data.frame(...) # 此处为用户原数据,省略重复定义
formula_1 <- function(P, PET, Q) {
  Anomaly_P = P - mean(P, na.rm = TRUE)
  Anomaly_PET = PET - mean(PET, na.rm = TRUE)
  Anomaly_Q = Q - mean(Q, na.rm = TRUE)
  return(list(Anomaly_P = Anomaly_P, Anomaly_PET = Anomaly_PET, Anomaly_Q = Anomaly_Q))
}

site_names <- sub(" P \\[mm\\]| PET \\[mm\\]| Q \\[mm\\]", "", names(df)[-1]) |> 
  unique()

# 初始化最终结果为原数据
df_final <- df

# 循环处理每个站点,插入异常值列
for (site in site_names) {
  # 定义原参数列名
  p_col <- paste0(site, " P [mm]")
  pet_col <- paste0(site, " PET [mm]")
  q_col <- paste0(site, " Q [mm]")
  
  # 计算异常值
  anomalies <- formula_1(df[[p_col]], df[[pet_col]], df[[q_col]])
  
  # 定义异常值列名
  anom_p_col <- paste0(site, " Anomaly_P [mm]")
  anom_pet_col <- paste0(site, " Anomaly_PET [mm]")
  anom_q_col <- paste0(site, " Anomaly_Q [mm]")
  
  # 插入异常值列到对应参数列之后
  p_pos <- which(names(df_final) == p_col)
  df_final <- add_column(df_final, !!anom_p_col := anomalies$Anomaly_P, .after = p_pos)
  
  pet_pos <- which(names(df_final) == pet_col)
  df_final <- add_column(df_final, !!anom_pet_col := anomalies$Anomaly_PET, .after = pet_pos)
  
  q_pos <- which(names(df_final) == q_col)
  df_final <- add_column(df_final, !!anom_q_col := anomalies$Anomaly_Q, .after = q_pos)
}

结果说明

两种方式均能实现预期目标:原数据中每个站点的P [mm]列后追加对应Anomaly_P [mm]列,PET [mm]列后追加Anomaly_PET [mm]列,Q [mm]列后追加Anomaly_Q [mm]列,同时保持时序数据的行顺序不变。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 14:07:02