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

如何用dplyr按行统计指定列两两组合的非NA值数量?

按行统计指定列两两组合的非NA值数量(dplyr简洁实现)

问题背景

现有如下数据框:

id    cog com emo
AUD-002 12  34  24
PAR-044 NA  28  38
BRE-019 0   NA  51
2-1-GRE NA  31  68

需要按行统计cog, com, emo所有列两两组合中两列均为非NA的情况,满足则标记为1,否则为0,期望输出:

id     cog com  emo cog-com cog-emo com-emo
AUD-002  12  34   24   1        1       1
PAR-044  NA  28   38   0        0       1
BRE-019  0   NA   51   0        1       0
2-1-GRE  NA  31   68   0        0       1

目前通过多次mutate语句可实现需求,但当列数较多时操作繁琐,需要更简洁的dplyr实现方式。

数据的dput如下:

structure(list(id = structure(c(2L, 4L, 3L, 1L), 
               .Label = c("2-1-GRE", "AUD-002", "BRE-019", "PAR-044"), 
               class = "factor"), 
               cog = c(12L, NA, 0L, NA), 
               com = c(34L, 28L, NA, 31L), 
               emo = c(24L, 38L, 51L, 68L)), 
           row.names = c(NA, -4L), class = "data.frame")

解决方案

可以通过批量生成列组合+dplyr批量创建新列的方式实现,无需手动编写多个mutate语句,代码可扩展性强(列数增多时仅需修改目标列列表):

方法1:结合rowwise()与c_across()

library(dplyr)

# 定义需要处理的目标列
target_cols <- c("cog", "com", "emo")
# 生成所有两两列组合
col_pairs <- combn(target_cols, 2, simplify = FALSE)

# 批量生成统计列
df_result <- df %>%
  rowwise() %>%
  mutate(
    !!!purrr::map(col_pairs, ~ {
      # 生成新列名(用"-"连接两个列名)
      new_col <- paste(.x, collapse = "-")
      # 判断当前行的两个列是否均为非NA,转成整数1/0
      val <- as.integer(all(!is.na(c_across(all_of(.x)))))
      # 绑定列名与对应值的表达式
      purrr::set_names(list(val), new_col)
    })
  ) %>%
  ungroup()

# 查看结果
print(df_result)

方法2:直接构造逻辑判断表达式(无需rowwise)

library(dplyr)
library(purrr)

target_cols <- c("cog", "com", "emo")
col_pairs <- combn(target_cols, 2, simplify = FALSE)

df_result <- df %>%
  mutate(
    !!!map(col_pairs, ~ {
      new_col <- paste(.x, collapse = "-")
      # 构造逻辑判断表达式:!is.na(col1) & !is.na(col2)
      expr <- parse_expr(paste0("as.integer(!is.na(", .x[1], ") & !is.na(", .x[2], "))"))
      set_names(list(expr), new_col)
    })
  )

print(df_result)

说明

  • 两种方法均能自动生成所有两两列组合的统计列,当目标列数量增加时,仅需修改target_cols向量即可,无需额外修改代码。
  • 核心逻辑是判断每行中两个列是否都不为NA,满足则返回1,否则返回0,与你之前的rowSums(!is.na(...)) -1逻辑一致(当两列均非NA时rowSums为2,减1得1;否则为0或-1,若数据存在两列均NA的场景,直接判断逻辑与的方式更准确)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 21:50:21