例如我的数据如下所示(实际数据集有 10,000 多行):
身份证 | 1160 | 1160 | 1216 | 1216 | 1132 | 1132 |
---|---|---|---|---|---|---|
01 | T | T | T | T | T | T |
02 | T | T | T | T | T | G |
03 | A | G | 不适用 | 不适用 | A | A |
04 | 我 | 我 | 我 | 我 | 我 | 我 |
05 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 | 不适用 |
06 | G | G | G | G | G | G |
我期待的结果是:
身份证 | 1160 | 1160 | 1216 | 1216 | 1132 | 1132 |
---|---|---|---|---|---|---|
02 | T | T | T | T | T | G |
03 | A | G | 不适用 | 不适用 | A | A |
您可以计算唯一值的数量并保留有多个的行。
dat[
sapply(data.frame(t(dat[, -1])), \(x) length(unique(na.omit(x))) > 1),
]
ID 1160 1160 1216 1216 1132 1132
2 2 T T T T T G
3 3 A G <NA> <NA> A A
或者如果你想要一个
dplyr
方法,你可以这样做:
library(dplyr)
dat |>
rowwise() |>
filter(n_distinct(na.omit(c_across(X1160:X1132.1))) > 1)
我怀疑这会慢得多。另外,我使用
check.names = TRUE
来修复此示例中的列名称,因为您有重复项。
dat <- structure(list(ID = 1:6, `1160` = c("T", "T", "A", "I", NA, "G"
), `1160` = c("T", "T", "G", "I", NA, "G"), `1216` = c("T", "T",
NA, "I", NA, "G"), `1216` = c("T", "T", NA, "I", NA, "G"), `1132` = c("T",
"T", "A", "I", NA, "G"), `1132` = c("T", "G", "A", "I", NA, "G"
)), class = "data.frame", row.names = c(NA, -6L))
在
apply
中使用 data.table
,其中 length(unique(na.omit(.)))
大于 1 的行的子集。
> library(data.table)
> setDT(dat)
> ss <- DT[, apply(.SD, 1, \(x) length(unique(na.omit(x))) > 1L), .SDcols=-"ID"]
> DT[ss]
ID X1160 X1160.1 X1216 X1216.1 X1132 X1132.1
1: 02 T T T T T G
2: 03 A G <NA> <NA> A A
也可以使用
data.table::uniqueN
,但速度很慢。
> dat[dat[, .I[uniqueN(unlist(.SD)) > 1], by = ID]$V1]
ID X1160 X1160.1 X1216 X1216.1 X1132 X1132.1
1: 02 T T T T T G
2: 03 A G <NA> <NA> A A
数据:
> dput(dat)
structure(list(ID = c("01", "02", "03", "04", "05", "06"), X1160 = c("T",
"T", "A", "I", NA, "G"), X1160.1 = c("T", "T", "G", "I", NA,
"G"), X1216 = c("T", "T", NA, "I", NA, "G"), X1216.1 = c("T",
"T", NA, "I", NA, "G"), X1132 = c("T", "T", "A", "I", NA, "G"
), X1132.1 = c("T", "G", "A", "I", NA, "G")), class = "data.frame", row.names = c(NA,
-6L))
使用
rowSums
的矢量化基础解决方案:
dat[rowSums(dat[,-(1:2)] != dat[,2], na.rm = TRUE) > 0,]
#> ID X1160 X1160.1 X1216 X1216.1 X1132 X1132.1
#> 2 02 T T T T T G
#> 3 03 A G <NA> <NA> A A
数据感谢@SamR:
dat <- structure(list(ID = 1:6, `1160` = c("T", "T", "A", "I", NA, "G"
), `1160` = c("T", "T", "G", "I", NA, "G"), `1216` = c("T", "T",
NA, "I", NA, "G"), `1216` = c("T", "T", NA, "I", NA, "G"), `1132` = c("T",
"T", "A", "I", NA, "G"), `1132` = c("T", "G", "A", "I", NA, "G"
)), class = "data.frame", row.names = c(NA, -6L))
首先,具有重复的列名并不是一个好主意。我使用
janitor::clean_names()
来获取唯一的列名称。
在
dplyr
中,我们可以基于多列使用if_all
或across
到filter
。见下图:
library(dplyr)
dat %>%
janitor::clean_names() %>%
filter(!if_all(x1160:x1132_2, ~ if_else(is.na(.x), TRUE, .x == x1160)))
#> id x1160 x1160_2 x1216 x1216_2 x1132 x1132_2
#> 1 2 T T T T T G
#> 2 3 A G <NA> <NA> A A
创建于 2024-01-09,使用 reprex v2.0.2