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

如何使用tidyverse风格方法按行移除数据框重复值并替换为NA

问题描述

我已经了解过多种使用base R实现按行处理、将行内重复值替换为NA的解决方案,可参考相关讨论:R - find all duplicates in row and replace。
但我想找到更符合tidy风格的实现方式。之前尝试了多种across用法,以及rowwise搭配c_across的组合方案,都没有得到正确结果。

使用的测试示例数据如下:

df <- data.frame(x = c(1, 2, 3, 4),
                 y = c(1, 3, 4, 5),
                 z = c(2, 3, 5, 6))

预期输出结果:

x  y  z
1 1 NA  2
2 2  3 NA
3 3  4  5
4 4  5  6

之前尝试的无效代码:

df |>
  mutate(apply(across(everything()), 1, function(x) replace(x, duplicated(x), NA)))

df |>
  mutate(apply(across(everything()), 1, function(x) {x[duplicated(x)] <- NA}))

我还尝试过创建存储重复值列位置的列表列,取得了部分进展,但该方法会触发“新名称”问题相关的冗余警告,不确定后续如何推进,也不确定这个思路是否可行,猜测可能需要借助purrr相关功能实现:

df |>
  rowwise() |>
  mutate(test = list(duplicated(c_across(everything())))) |>
  unnest_wider(test)

# A tibble: 4 × 6
      x     y     z ...1  ...2  ...3 
  <dbl> <dbl> <dbl> <lgl> <lgl> <lgl>
1     1     1     2 FALSE TRUE  FALSE
2     2     3     3 FALSE FALSE TRUE 
3     3     4     5 FALSE FALSE FALSE
4     4     5     6 FALSE FALSE FALSE
解决方案

以下两种均为标准tidy风格实现,无冗余警告,运行后直接输出预期结果:

  • 方案1适配常规dplyr操作链,可直接嵌入现有mutate流程
  • 方案2逻辑更直观,后续扩展自定义行处理规则更方便

方案1:rowwise + across 逐列判断

利用cur_column()匹配当前列在整行中的位置,直接判断当前值是否为行内重复值,是则替换为NA:

library(tidyverse)

df |>
  rowwise() |>
  mutate(
    across(
      everything(),
      ~{
        row_val <- c_across(everything())
        ifelse(duplicated(row_val)[which(names(row_val) == cur_column())], NA, .x)
      }
    )
  ) |>
  ungroup()

方案2:purrr::pmap 按行遍历处理

直接对数据框按行映射,每一行传入后将重复值替换为NA,再按行绑定为结果数据框:

df |>
  pmap_dfr(
    ~{
      row <- c(...)
      row[duplicated(row)] <- NA
      row
    }
  )

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 19:57:27