如何在DataFrame中仅移除非空testIds的重复项并保留所有空值?
解决DataFrame中仅移除非空testId重复项、保留所有空值的问题
我明白你遇到的困扰:想去掉testId列里非空值的重复项,但要保留所有的NA,之前的代码要么把NA也删了,要么循环没起作用。咱们一步步来解决这个问题。
问题出在哪?
你之前用的df3[!duplicated(df3$testId),]会把重复的NA也删掉,因为duplicated()默认把NA视为相等的值——也就是说,如果有10个NA行,这个代码只会留下第一个,其他9个都被过滤掉了。而你写的循环其实没起到筛选作用:不管j是TRUE还是FALSE,你都执行了同样的去重逻辑,自然结果和之前一样。
最简单的解决方案(基础R)
用一行代码就能搞定,核心是把「非重复的非NA行」和「所有NA行」都保留下来:
df4 <- df3[!duplicated(df3$testId) | is.na(df3$testId), ]
逻辑拆解:
!duplicated(df3$testId):标记所有非重复的非NA行(只保留每个非空testId的第一次出现)is.na(df3$testId):标记所有NA行|(逻辑或):把这两类行都保留,既去除了非空值的重复,又保住了所有NA
如果你习惯用dplyr
可以用分组筛选的方式,确保非NA值只留第一行,NA值全部保留:
library(dplyr) df4 <- df3 %>% group_by(testId) %>% filter(row_number() == 1 | is.na(testId)) %>% ungroup()
或者拆分两步:先提取非NA的唯一行,再合并所有NA行:
df4 <- df3 %>% filter(!is.na(testId)) %>% distinct(testId, .keep_all = TRUE) %>% bind_rows(df3 %>% filter(is.na(testId)))
验证一下效果
假设你的数据是这样的:
df3 <- data.frame( testId = c("A", "A", NA, "B", NA, "C"), value = 1:6 )
运行上面的基础R代码后,df4会保留:
- 第一个"A"行
- 所有NA行
- 第一个"B"行
- 第一个"C"行
也就是结果完全符合你的需求:
| testId | value |
|---|---|
| A | 1 |
| NA | 3 |
| B | 4 |
| NA | 5 |
| C | 6 |
内容的提问来源于stack exchange,提问作者Talia Wadermann
相关产品推荐
相关产品推荐

