Вы были близки, ваша идея использовать sapply
с примитивной функцией !=
в основном верна.
Следующее возвращает логическую матрицу.
sapply(dat, `!=`, "X")
# COL1 COL2
#[1,] FALSE FALSE
#[2,] FALSE FALSE
#[3,] FALSE TRUE
#[4,] FALSE FALSE
#[5,] TRUE FALSE
Если вам нужны номера строк, оберните их в which
с аргументом arr.ind
, установленным в TRUE
.
which(sapply(dat, `!=`, "X"), arr.ind = TRUE)
# row col
#[1,] 5 1
#[2,] 3 2
Редактировать.
Было опубликовано несколько решений, вот сравнительные тесты.
Поскольку ОП говорит, что могут быть наборы данных с 100 столбцами, я проверил с двумяразные наборы данных, размещенные в вопросе и больший.
Функция RuiJaap
равна Rui
с предложением в комментарии Jaap.
Rui <- function(DF, value = "X")
which(sapply(DF, `!=`, value), arr.ind = TRUE)
DanY <- function(DF, value = "X")
unique(sapply(DF, function(x) which(x != value)))
Jaap <- function(DF, value = "X")
which(!!rowSums(DF != value))
RuiJaap <- function(DF, value = "X")
which(dat != "X", arr.ind = TRUE)
library(ggplot2)
library(microbenchmark)
mb1 <- microbenchmark(Rui = Rui(dat),
RuiJaap = RuiJaap(dat),
Jaap = Jaap(dat),
DanY = DanY(dat),
times = 1e3)
mb2 <- microbenchmark(Rui = Rui(dat2),
RuiJaap = RuiJaap(dat2),
Jaap = Jaap(dat2),
DanY = DanY(dat2),
times = 1e2)
autoplot(mb1)
autoplot(mb2)
Для небольших наборов данных DanY
быстрее, но для больших, RuiJaap
- самое быстрое.
Данные.
dat <- read.table(text = "
COL1 COL2
1 X X
2 X X
3 X Y
4 X X
5 Z X
", header = TRUE)
set.seed(1)
dat2 <- matrix("X", nrow = 20, ncol = 100)
dat2[sample(2000, 100)] <- "Y"
dat2 <- as.data.frame(dat2)