过滤所选列中至少具有两个不同值的行

问题描述 投票:0回答:4

例如我的数据如下所示(实际数据集有 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
r dataframe subset
4个回答
2
投票

您可以计算唯一值的数量并保留有多个的行。

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))

2
投票

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))

1
投票

使用

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))

0
投票

首先,具有重复的列名并不是一个好主意。我使用

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

© www.soinside.com 2019 - 2024. All rights reserved.