У меня есть dataframe с четырьмя логическими векторами, v1, v2, v3, v4, которые ИСТИНА или ЛОЖЬ. Мне нужно классифицировать каждую строку dataframe на основе комбинации из булевых векторов (например, «None», «v1 только», «v1 и v3», «Все», и т.д.). Я хотел бы сделать это, не взяв подмножество фрейма данных или вложенные операторы ifelse. Любые предложения по наилучшему способу сделать это? Благодаря!Сравнение булевых векторов
ответ
Похоже, я Арри поздно на этой вечеринке. Тем не менее, я мог бы также поделиться тем, что я принес!
Это работает путем обработки 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
Вот один из подходов, основанный на том, что TRUE/FALSE
может быть представлен как 0s и 1s. Вы можете умножить логические значения на их индекс столбца, а затем вставить все значения вместе. Это скажет вам, какие столбцы имели значение 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
....
+1 Красиво сделано. Другим вариантом, также использующим представление 0/1, было бы умножение каждого на мощность 10 и добавление; это можно сделать с помощью умножения на матрицу, например, 'as.matrix (dat)% *% 10^rev (seq_len (ncol (dat)) - 1)'. (Или используйте мощность 2, если вы предпочитаете думать в двоичном формате.) – Aaron
+1, но я не вижу необходимости в «индексе столбца», так как он определяется положением '1' в строке. Альтернативы были бы "apply (1 * dat, 1, paste, collapse =" ")' или 'do.call (paste, c (1 * dat, sep =" "))'. –
Спасибо.Поэтому, основываясь на вашем ответе, я думаю о следующем: 'v1 <- ifelse (v1 == TRUE, 1000, 0)' 'v2 <- ifelse (v1 == TRUE, 100, 0)' 'v3 <- ifelse (v1 == TRUE, 10, 0) '' v4 <- ifelse (v1 == TRUE, 1, 0) '' dat $ v5 <- sum (v1, v2, v3, v4) 'Должен ли я затем создать список значений для поиска метки (например, 1111 == «Все») или есть лучший способ? –
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
Вторая стратегия concatentate имена столбцов в истинах, используя разделитель «»:
> 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
Спасибо. Я многому научился и от этого ответа. –
Позвольте мне бросить шляпу в кольцо, а
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! Регулярные выражения могут дополнительно уточнить это, заменив все, кроме последнего 'и' на ','. Вот что должно работать: 'txt <-" v1 и v2 и v3 и v4 "', затем 'gsub (" ([[: space:]] и) (?! [[: Space:]] v [[: digit:]] $) ",", ", txt, perl = TRUE). –
- 1. Инициализировать номера для булевых векторов
- 2. Сравнение векторов
- 3. Сравнение векторов
- 4. Сравнение булевых массивов Java
- 5. Сравнение векторов в массиве векторов
- 6. Сравнение значений двумерных булевых массивов?
- 7. Сравнение двух векторов
- 8. Сравнение двух векторов (Java)
- 9. C++ Сравнение векторов
- 10. Сравнение векторов различной длины
- 11. Сравнение двух векторов
- 12. Сравнение векторов контекста
- 13. Сравнение нескольких векторов
- 14. Сравнение различных векторов
- 15. torch.Tensor манипуляции - Сравнение двух векторов
- 16. Сравнение двух векторов (предсказано/ожидалось)
- 17. Octave - сравнение векторов (по элементам)
- 18. Сравнение векторов и печати bool
- 19. R: Сравнение двух двоичных векторов
- 20. Эффективное сравнение 100 000 векторов
- 21. Эффективное сравнение малых целых векторов
- 22. Хранение и сравнение многомерных векторов
- 23. Сравнение булевых совпадений Java с тройным оператором
- 24. Сравнение одиночного байта вместо нескольких булевых сравнений
- 25. R Сравнение и сравнение значений с разных векторов
- 26. сравнение векторов строк, чтобы получить разницу
- 27. Сравнение и устранение элементов векторов в R
- 28. сравнение двух векторов, сделать его более эффективным
- 29. Сравнение нескольких векторов одновременно в R?
- 30. Сравнение двух векторов самым эффективным способом
Спасибо! Если я добавлю 'df $ v3 <- TRUE', а затем попробую запустить ' df $ description <- apply (df, 1, getDescription) 'снова, я получаю следующую ошибку: ** Ошибка в X * c (1, 2, 4): нечисловой аргумент для двоичного оператора ** Любые идеи, почему это происходит? Благодаря! –
@BoomShakalaka - Это прекрасно работает для меня. Возможно, вы назначили «TRUE» вместо «TRUE»? Ваше сообщение об ошибке означает, что один столбец в вашем файле data.frame не является числовым. Кроме того, ваш 'df' имеет больше, чем только три столбца? Если это так, вам нужно будет выполнить «apply» (df [c («v1», «v2», «v3»)], 1, getDescription). Надеюсь, это поможет. –
Существует еще один столбец, который не является числовым, так что это проблема. Благодаря! –