Как получить номера строк с конкретными данными? - PullRequest
0 голосов
/ 08 октября 2018

У меня есть data.frame

          COL1         COL2 
1          X            X
2          X            X
3          X            Y
4          X            X
5          Z            X

Если в столбце нет XI, необходимо получить номер соответствующей строки (3 и 5 в этом случае).Я пытался использовать «sapply» для проверки данных через «! =», Но я думаю, что мне нужно что-то еще.

Ответы [ 5 ]

0 голосов
/ 08 октября 2018

Вот базовое решение R, которое будет работать для любого количества столбцов -

which(rowSums(df == "X") != ncol(df))

0 голосов
/ 08 октября 2018

Вот решение tidyverse, которое может работать с произвольным числом столбцов

library(tidyverse)

df <- tibble(
 col1 = c("X", "X", "X", "X", "Z"),
 col2 = c("X", "X", "Z", "X", "X"),
 col3 = c("X", "X", "Z", "Z", "X"),
)

filter_all(df, any_vars(. != "X"))

, которое возвращает:

# A tibble: 3 x 3
 col1  col2  col3
  <chr> <chr> <chr>
  1     X     Z     Z
  2     X     X     Z
  3     Z     X     X
0 голосов
/ 08 октября 2018

Это будет работать:

library(dplyr)
filter(df, (COL1!="X" & COL2!="X"))
0 голосов
/ 08 октября 2018

Вы были близки, ваша идея использовать 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)
0 голосов
/ 08 октября 2018

Вот решение, использующее which, которое будет работать с любым количеством столбцов:

# example data
df <- data.frame(
    col1 = c("X", "X", "X", "X", "Z"),
    col2 = c("X", "X", "Z", "X", "X"),
    stringsAsFactors = FALSE
)

# how to get rows without X
unique(sapply(df, function(x) which(x != "X")))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...