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

自定义函数结合dplyr across()报错问题排查

批量统计多列值为1时的唯一ID数量

数据与需求

给定数据框:

dat <- data.frame(ID=c("12345", "54321", "12345", "54321", "99999", "12345"),
                  cat1 = c(1,0,0,0,0,0),
                  cat2= c(1,1,1,1,1,1),
                  cat3= c(1,0,1,0,1,0),
                  cat4=c(0,0,0,0,0,0))

需要统计每一列值为1时对应的唯一ID数量,期望输出:

cat1 1
cat2 3
cat3 2
cat4 0

错误原因分析

你编写的自定义函数结合summarise(across())时出现报错,核心问题是:

  • across()在迭代每一列时,传递给.fns(即你的my_function)的.x是当前列的数值向量(比如cat1的c(1,0,0,0,0,0)),而不是整个数据框。
  • 你的my_function第一个参数data期望接收数据框,却传入了单个数值向量,导致filter()无法处理向量类型的数据,触发报错:no applicable method for 'filter' applied to an object of class "c('double', 'numeric')"。

正确解法

解法1:直接在across()内实现逻辑(最简)

不需要自定义函数,直接利用.x指代当前列向量,筛选出该列值为1对应的ID后统计去重数量:

dat |>
  summarise(across(c(cat1, cat2, cat3, cat4), ~n_distinct(ID[.x == 1])))

运行后输出:

cat1 cat2 cat3 cat4
1    1    3    2    0

解法2:修改自定义函数适配across()

调整函数参数,让它接收列向量和ID向量,而非整个数据框:

my_function <- function(col_vec, id_vec) {
  n_distinct(id_vec[col_vec == 1])
}

# 调用函数
dat |>
  summarise(across(c(cat1, cat2, cat3, cat4), ~my_function(.x, ID)))

解法3:重塑数据后统计(更直观)

通过pivot_longer将宽表转为长表,分组统计后补全缺失类别:

library(tidyr)

dat |>
  pivot_longer(cols = starts_with("cat"), names_to = "category", values_to = "value") |>
  filter(value == 1) |>
  group_by(category) |>
  summarise(n = n_distinct(ID)) |>
  complete(category = paste0("cat", 1:4), fill = list(n = 0))

输出结果:

# A tibble: 4 × 2
  category     n
  <chr>    <int>
1 cat1         1
2 cat2         3
3 cat3         2
4 cat4         0

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 06:57:18