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

如何处理dplyr/across中数据框列数不匹配的报错问题

解决dplyr across列数不匹配的问题

问题出在across(contains("_2023"))返回2列,而across(contains("_2022"))返回3列,两者列数不等导致除法运算报错。要实现“无匹配列时返回NA”,可以用以下两种方法:

方法1:遍历2022指标并匹配2023列

直接针对每个2022年的指标,检查是否存在对应2023年列,存在则计算增长,不存在则返回NA:

library(tidyverse)

raw_data_2 <- data.frame(category=c('A','B','C'),
                       sales_2022=c(1,2,3),
                       profit_2022=c(0.1,0.4,0.3),
                       margin_2022=c(0.2,0.8,0.6),
                       sales_2023=c(1.5,3,4),
                       margin_2023=c(0.3,0.7,0.5)
                       )

# 提取所有2022年的指标名称(去掉_2022后缀)
metrics <- str_remove(names(raw_data_2)[str_detect(names(raw_data_2), "_2022")], "_2022")

# 计算各指标的增长,无2023列则返回NA
raw_data_2 %>%
  mutate(
    across(all_of(metrics),
           ~ {
             col_2023 <- paste0(cur_column(), "_2023")
             if (col_2023 %in% names(raw_data_2)) {
               (!!sym(col_2023) / .x) - 1
             } else {
               NA_real_
             }
           },
           .names = "{col}_increase")
  )

运行后会生成sales_increase、profit_increase(全为NA)、margin_increase三列,符合需求。

方法2:转成长格式处理(更直观)

通过tidyr的pivot函数将数据转成长格式,统一计算增长后再转回宽格式,自动处理缺失列:

raw_data_2 %>%
  # 转成长格式,拆分指标和年份
  pivot_longer(-category,
               names_to = c("metric", "year"),
               names_pattern = "(.*)_(\\d{4})") %>%
  # 转回宽格式,按指标分2022和2023列
  pivot_wider(names_from = year, values_from = value) %>%
  # 计算增长值,无2023列则自动为NA
  mutate(increase = (`2023` / `2022`) - 1) %>%
  # 转回原宽格式,生成各指标的增长列
  pivot_wider(names_from = metric,
              values_from = c(`2022`, `2023`, increase),
              names_glue = "{metric}_{.value}") %>%
  # 调整增长列的名称(去掉_increase后缀)
  rename_with(~ str_remove(., "_increase"), ends_with("_increase"))

这种方法更适合指标较多的场景,无需手动提取指标列表,自动适配所有存在的2022指标。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 22:43:21