R: Есть ли в R команда «Un-Character»?

Я работаю с языком программирования R.

У меня есть следующий набор данных:

v <- c(1,2,3,4,5,6,7,8,9,10)

var_1 <- as.factor(sample(v, 10000, replace=TRUE, prob=c(0.1,0.1,0.1,0.1,0.1, 0.1,0.1,0.1,0.1,0.1)))

var_2 <- as.factor(sample(v, 10000, replace=TRUE, prob=c(0.1,0.1,0.1,0.1,0.1, 0.1,0.1,0.1,0.1,0.1)))

var_3 <- as.factor(sample(v, 10000, replace=TRUE, prob=c(0.1,0.1,0.1,0.1,0.1, 0.1,0.1,0.1,0.1,0.1)))

var_4 <- as.factor(sample(v, 10000, replace=TRUE, prob=c(0.1,0.1,0.1,0.1,0.1, 0.1,0.1,0.1,0.1,0.1)))

var_5 <- as.factor(sample(v, 10000, replace=TRUE, prob=c(0.1,0.1,0.1,0.1,0.1, 0.1,0.1,0.1,0.1,0.1)))

my_data = data.frame(var_1, var_2, var_3, var_4, var_5)

У меня также есть другой набор данных «условий», который будет использоваться для запроса этого фрейма данных:

conditions = data.frame(cond_1 = c("1,3,4", "4,5,6"), cond_2 = c("5,6", "7,8,9"))

Мой вопрос: Я попытался выполнить следующую команду для выбора строк из "my_data" на основе первой строки "условий", но это возвращает пустой результат:

my_data[my_data$var_1 %in% unlist(conditions[1,1]) &
            my_data$var_2 %in% unlist(conditions[1,2]), ]

[1] var_1 var_2 var_3 var_4 var_5
<0 rows> (or 0-length row.names)

Я попытался подробнее изучить это, «проверив» эти условия:

class(conditions[1,1])
[1] "character"

Это заставляет меня думать, что команда «unlist()» не работает, потому что сами условия являются «символом», а не «списком».

Есть ли эквивалентная команда, которую можно использовать здесь, которая играет ту же роль, что и команда «unlist ()», чтобы можно было запустить приведенный выше оператор?

В общем, я пытаюсь получить те же результаты, что и этот код, но сохраняя формат, который я использовал выше:

my_data[my_data$var_1 %in% c("1", "3", "4") &
            my_data$var_2 %in% c("5", "6"), ]

Спасибо!

Справка:Выбор строк данных на основе нескольких условий

Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
3
0
51
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Впереди, "1,3,4" != 1. Кажется, вам следует попытаться разделить строки с помощью strsplit(., ",").

expected <- my_data[my_data$var_1 %in% c("1", "3", "4") & my_data$var_2 %in% c("5", "6"), ]
head(expected)
#     var_1 var_2 var_3 var_4 var_5
# 18      3     6     2     2     9
# 129     3     5     3     2     8
# 133     4     5     6     5     8
# 186     1     6     6    10    10
# 204     4     6     4     2     6
# 207     1     5     3     2     9

out <- my_data[do.call(`&`, 
  Map(`%in%`,
      lapply(my_data[,1:2], as.character), 
      lapply(conditions, function(z) strsplit(z, ",")[[1]]))),]
head(out)
#     var_1 var_2 var_3 var_4 var_5
# 18      3     6     2     2     9
# 129     3     5     3     2     8
# 133     4     5     6     5     8
# 186     1     6     6    10    10
# 204     4     6     4     2     6
# 207     1     5     3     2     9

Редактировать: обновление для новых conditions: изменить do.call на Reduce:

conditions = data.frame(cond_1 = c("1,3,4", "4,5,6"), cond_2 = c("5,6", "7,8,9"), cond_3 = c("4,6", "9"))
out <- my_data[Reduce(`&`,
  Map(`%in%`,
      lapply(my_data[,1:3], as.character),
      lapply(conditions, function(z) strsplit(z, ",")[[1]]))),]
head(out)
#     var_1 var_2 var_3 var_4 var_5
# 133     4     5     6     5     8
# 186     1     6     6    10    10
# 204     4     6     4     2     6
# 232     1     5     6     5     8
# 332     3     6     6     5    10
# 338     1     5     6     3     6

Большое спасибо за ваш ответ! Я пытаюсь проверить, работает ли ваш ответ, если количество столбцов в фрейме данных «условия» превышает 2. Например:

stats_noob 10.04.2022 07:33

условия = data.frame(cond_1 = c("1,3,4", "4,5,6"), cond_2 = c("5,6", "7,8,9"), cond_3 = c( "4,6", "9"))

stats_noob 10.04.2022 07:33

out <- my_data[do.call(&, Map(%in%, lapply(my_data[,1:3], as.character), lapply(условия, функция(z) strsplit(z, ",")[[1] ]))),]

stats_noob 10.04.2022 07:33

Ошибка в .Primitive("&")(var_1 = c(FALSE, FALSE, TRUE, FALSE, FALSE, FALSE,: 3 аргумента переданы в '&', для которых требуется 2

stats_noob 10.04.2022 07:33

Может ли предоставленный вами код работать с несколькими условиями, хранящимися в нескольких столбцах? Большое спасибо!

stats_noob 10.04.2022 07:34

Смотрите мою правку. Вместо этого используйте Reduce.

r2evans 10.04.2022 07:36

@ r2evans: теперь это работает! Я даже добавил столбец с 4 условиями и попробовал ваш код с 4 условиями (lapply(my_data[,1:4])... и все работает! Интересно, почему более ранний код не обобщает так же хорошо, как отредактированный код - У вас есть идеи, почему это может происходить? Большое спасибо за вашу помощь!

stats_noob 10.04.2022 07:39

Ну, во-первых, "1,3,4" — это не то, что у вас в колонках. Его нужно разделить на отдельные компоненты, чтобы сравнить с чем-либо еще.

r2evans 10.04.2022 08:08

Слишком долго для комментария, но поскольку я ответил на ваш предыдущий вопрос, я заметил важную разницу в том, как выглядят ваши кадры данных conditions. Возможно, это и есть причина вашего замешательства.

Я предполагаю, что вам нужны/нужны списки в ячейках, но в этой версии у вас есть строки, которые нужно разделить, как @r2evans показал вам отличный отвечать.

Чтобы создать фрейм данных conditions, который больше похож на ваш предыдущий вопрос, вы можете использовать list2DF (также см. соответствующий отвечать).

conditions1 <- list2DF(list(cond_1=list(c(1, 3, 4), c(4, 5, 6)), 
                            cond_2=list(c(5, 6), c(7, 8, 9))))
conditions1
#    cond_1  cond_2
# 1 1, 3, 4    5, 6
# 2 4, 5, 6 7, 8, 9

куда:

str(conditions1)
# 'data.frame': 2 obs. of  2 variables:
#   $ cond_1:List of 2
# ..$ : num  1 3 4
# ..$ : num  4 5 6
# $ cond_2:List of 2
# ..$ : num  5 6
# ..$ : num  7 8 9

Ваш conditions похож

conditions
#   cond_1 cond_2
# 1  1,3,4    5,6
# 2  4,5,6  7,8,9

но:

str(conditions)
# 'data.frame': 2 obs. of  2 variables:
# $ cond_1: chr  "1,3,4" "4,5,6"
# $ cond_2: chr  "5,6" "7,8,9"

Используйте данные, сгенерированные в примечании в конце. Он использует set.seed, чтобы сделать его воспроизводимым, а также использует уменьшенное количество строк, поскольку точку можно проиллюстрировать с меньшим количеством строк.

1) sqldf Сгенерируйте строку условия cond, которая для этого примера равна "var_1 in (1,3,4) and var_2 in (5,6)", а затем вставьте ее в оператор SQL, который мы запускаем.

library(sqldf)

nc <- ncol(conditions)    
s <- sprintf("%s in (%s)", names(my_data)[1:nc], conditions[1, ])
cond <- paste(s, collapse = " and ")

fn$sqldf("select * from my_data where $cond")
##   var_1 var_2 var_3 var_4 var_5
## 1     1     6     8     6     1
## 2     4     6    10     8     7

# check

my_data[my_data$var_1 %in% c("1", "3", "4") & my_data$var_2 %in% c("5", "6"), ]
##    var_1 var_2 var_3 var_4 var_5
## 11     1     6     8     6     1
## 17     4     6    10     8     7

2) подмножество Сгенерируйте соответствующую строку условия cond, которая в данном случае равна "var_1 %in% c(1,3,4) & var_2 %in% c(5,6)", а затем проанализируйте и запустите subset на ней, используя do.call.

nc <- ncol(conditions)
s <- sprintf("%s %%in%% c(%s)", names(my_data)[1:nc], conditions[1, ])
cond <- paste(s, collapse = " & ")

do.call("subset", list(my_data, parse(text = cond)))

##    var_1 var_2 var_3 var_4 var_5
## 11     1     6     8     6     1
## 17     4     6    10     8     7

Примечание

set.seed(123)

conditions <- data.frame(cond_1 = c("1,3,4", "4,5,6"), 
                         cond_2 = c("5,6", "7,8,9"))

n <- 10   # sample from 1:n
nr <- 25  # no of rows
nc <- 5   # no of columns

prob <- rep(0.1, n)
nms <- paste0("var_", 1:nc)  # column names

L <- Map(function(x) as.factor(sample(n, nr, TRUE, prob)), nms)
my_data <- as.data.frame(L)

Другие вопросы по теме