Сравнение булевых векторов - PullRequest
4 голосов
/ 14 декабря 2011

У меня есть кадр данных с четырьмя логическими векторами: v1 , v2 , v3 , v4 , которые имеют значение ИСТИНА или ЛОЖЬ.Мне нужно классифицировать каждую строку кадра данных на основе комбинации логических векторов (например, "Нет" , "только v1" , "v1 и v3", «Все» и т. Д.).Я хотел бы сделать это, не принимая подмножество фрейма данных или вложенные операторы ifelse.Какие-нибудь предложения для лучшего способа сделать это?Спасибо!

Ответы [ 4 ]

3 голосов
/ 14 декабря 2011

Похоже, я опоздал на эту вечеринку.Тем не менее, я мог бы также поделиться тем, что я принес!

Это работает, обрабатывая возможности FALSE/TRUE как биты и воздействуя на них, чтобы назначить каждой комбинации v1, v2 и v3 уникальное целое число от 1 до 8 (очень похоже наchmod может представлять биты разрешений в системах *NIX).Затем целое число используется в качестве индекса для выбора соответствующего элемента вектора текстовых дескрипторов.

(Для демонстрации я использовал только три столбца, но этот подход хорошо масштабируется.)

# CONSTRUCT VECTOR OF DESCRIPTIONS
description <- c("None", "v1", "v2", "v1 and v2",
                 "v3", "v1 and v3", "v2 and v3", "All")

# DEFINE DESCRIPTION FUNCTION
getDescription <- function(X) {
    index <- 1 + sum(X*c(1,2,4))
    description[index]
}

# TRY IT OUT ON ALL COMBOS OF v1, v2, and v3
df <- expand.grid(v1=c(FALSE, TRUE),
                  v2=c(FALSE, TRUE),
                  v3=c(FALSE, TRUE))
df$description <- apply(df, 1, getDescription)

# YEP, IT WORKS.
df
#      v1    v2    v3 description
# 1 FALSE FALSE FALSE        None
# 2  TRUE FALSE FALSE          v1
# 3 FALSE  TRUE FALSE          v2
# 4  TRUE  TRUE FALSE   v1 and v2
# 5 FALSE FALSE  TRUE          v3
# 6  TRUE FALSE  TRUE   v1 and v3
# 7 FALSE  TRUE  TRUE   v2 and v3
# 8  TRUE  TRUE  TRUE         All
3 голосов
/ 14 декабря 2011

Вот один из подходов, основанный на том факте, что TRUE / FALSE можно представить в виде 0 и 1. Вы можете умножить логические значения на их индекс столбца, а затем вставить все значения вместе. Это скажет вам, какие столбцы имеют значение 1 для каждой строки. Вот пример:

set.seed(1)
dat <- data.frame(v1 = sample(c(T,F), 10, TRUE),
                  v2 = sample(c(T,F), 10, TRUE),
                  v3 = sample(c(T,F), 10, TRUE),
                  v4 = sample(c(T,F), 10, TRUE)
                  )
#End fake data
#Multiple T/F times the column index
dat <- dat * rep(seq_len(ncol(dat)), each = nrow(dat))
#Paste together in a new column
dat$v5 <- apply(dat, 1, function(x) paste(x, collapse = ""))

> dat
   v1 v2 v3 v4   v5
1   0  0  3  4 0034
2   0  2  0  4 0204
...

Включая полезные комментарии ниже и дополнительный вопрос

Я бы создал таблицу подстановки, используя expand.grid(), а затем написал бы текстовые метки, чтобы представлять их, как вы считаете нужным. Вот пример с двумя столбцами:

set.seed(1)
dat <- data.frame(v1 = sample(c(T,F), 10, TRUE),
                  v2 = sample(c(T,F), 10, TRUE)
       )

#Thanks @Joshua
dat$comp <- as.character(apply(1 * dat, 1, paste, collapse=""))

#Look up table
lookup <- data.frame(comp = apply(expand.grid(0:1, 0:1), 1, paste, collapse = ""),
                     text = c("none", "v1 only", "v2 only", "all"),
                     stringsAsFactors = FALSE
)

#Use merge to join the look up table to your data. Note the consistent naming of the comp column
> merge(dat, lookup)
   comp    v1    v2    text
1    00 FALSE FALSE    none
2    00 FALSE FALSE    none
3    01 FALSE  TRUE v2 only
....
2 голосов
/ 14 декабря 2011

Позвольте мне также бросить свою шляпу на ринге

plyr::adply(dat, 1, function(x) paste(names(Filter(isTRUE, x)), collapse = " and "))

      v1    v2    v3    v4               V1
1   TRUE  TRUE FALSE  TRUE v1 and v2 and v4
2   TRUE  TRUE  TRUE FALSE v1 and v2 and v3
3  FALSE FALSE FALSE  TRUE               v4
4  FALSE  TRUE  TRUE  TRUE v2 and v3 and v4
5   TRUE FALSE  TRUE FALSE        v1 and v3
6  FALSE  TRUE  TRUE FALSE        v2 and v3
7  FALSE FALSE  TRUE FALSE               v3
8  FALSE FALSE  TRUE  TRUE        v3 and v4
9  FALSE  TRUE FALSE FALSE               v2
10  TRUE FALSE  TRUE  TRUE v1 and v3 and v4
1 голос
/ 14 декабря 2011
 set.seed(123)
> dat <- data.frame(v1 = sample(c(T,F), 10, TRUE),
+                   v2 = sample(c(T,F), 10, TRUE),
+                   v3 = sample(c(T,F), 10, TRUE),
+                   v4 = sample(c(T,F), 10, TRUE)
+                   )
> dat

Первая стратегия использует различные комбинации шаблонов для индексации в вектор символа со значением по умолчанию 1 для индекса "Другое":

> dat$bcateg <- c("Other", "v2 only", "v1 and v3", "All")[1+
+ with(dat, 1*(v2 & !v1 &!v3 &!v4))
+ +with(dat, 2*(v1&v3))+
+ with(dat, v1&v2&v3&v4)]
> dat
      v1    v2    v3    v4    bcateg
1   TRUE FALSE FALSE FALSE     Other
2  FALSE  TRUE FALSE FALSE   v2 only
3   TRUE FALSE FALSE FALSE     Other
4  FALSE FALSE FALSE FALSE     Other
5  FALSE  TRUE FALSE  TRUE     Other
6   TRUE FALSE FALSE  TRUE     Other
7  FALSE  TRUE FALSE FALSE   v2 only
8  FALSE  TRUE FALSE  TRUE     Other
9  FALSE  TRUE  TRUE  TRUE     Other
10  TRUE FALSE  TRUE  TRUE v1 and v3

Вторая стратегия объединяет имена столбцовИСТИНА, используя разделитель ",":

> dat$bcateg2 <-paste( c("","v1")[dat[["v1"]]+1 ], c("","v2")[dat[["v2"]]+1 ], c("","v3")[dat[["v3"]]+1 ], c("","v4")[dat[["v4"]]+1 ], sep = ",")
> dat
      v1    v2    v3    v4    bcateg   bcateg2
1   TRUE FALSE FALSE FALSE     Other     v1,,,
2  FALSE  TRUE FALSE FALSE   v2 only     ,v2,,
3   TRUE FALSE FALSE FALSE     Other     v1,,,
4  FALSE FALSE FALSE FALSE     Other       ,,,
5  FALSE  TRUE FALSE  TRUE     Other   ,v2,,v4
6   TRUE FALSE FALSE  TRUE     Other   v1,,,v4
7  FALSE  TRUE FALSE FALSE   v2 only     ,v2,,
8  FALSE  TRUE FALSE  TRUE     Other   ,v2,,v4
9  FALSE  TRUE  TRUE  TRUE     Other ,v2,v3,v4
10  TRUE FALSE  TRUE  TRUE v1 and v3 v1,,v3,v4
...