Группируйте с помощью str_detect для групп с похожими строками

Рассмотрим этот пример данных:

library(tidyverse)

dt <- tibble(Poison = c('Arsenic', 'Arsenic in Wine', 'Cyanide', 'Cyanide and Sugar'),
             Result = c('Death', 'Death With Class', 'Death', 'Death'))

Я хочу создать столбец, который присваивает каждой группе идентификационный номер. Однако я хочу, чтобы яды были сгруппированы вместе по строковому обнаружению, то есть «Мышьяк» и «Мышьяк в вине» были одной группой, а «Цианид» и «Цианид и сахар» — другой группой. В настоящее время R считает, что каждая группа является своей собственной, как таковая:

dt <- dt %>%
  group_by(Poison) %>%
  mutate(Group = n())
# A tibble: 4 × 3
# Groups:   Poison [4]
  Poison            Result           Group
  <chr>             <chr>            <int>
1 Arsenic           Death                1
2 Arsenic in Wine   Death With Class     1
3 Cyanide           Death                1
4 Cyanide and Sugar Death                1

Я хочу, чтобы «Мышьяк» и «Мышьяк в вине» относились к группе 1, а «Цианид» и «Цианид и сахар» - к группе 2. Есть идеи?

Забыл вторую половину кадра данных, добавил ее!

ksinva 05.04.2024 18:17

Знаете ли вы заранее все группы? То есть у вас есть (где-то) c("Arsenic", "Cyanide")?

r2evans 05.04.2024 18:18
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
2
59
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

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

Комбинация case_when и grepl может быть полезна:

dt %>% 
  mutate(Group = case_when(
    grepl("Arsenic", Poison) ~ 1,
    grepl("Cyanide", Poison) ~ 2
  ))
# A tibble: 4 × 3
  Poison            Result           Group
  <chr>             <chr>            <dbl>
1 Arsenic           Death                1
2 Arsenic in Wine   Death With Class     1
3 Cyanide           Death                2
4 Cyanide and Sugar Death                2

Если вы не хотите записывать Пуассон, это может быть полезно:

dt %>% 
  mutate(Group = sub(" .*", "", Poison) %>% 
           as.factor %>% 
           as.integer())

Я определенно не хочу расписывать яды, так что спасибо за это предостережение! Отлично работает, большое спасибо!

ksinva 05.04.2024 19:28

Если мы заранее знаем вектор «кратчайших шаблонов»,

vec <- c("Arsenic", "Cyanide")
### or perhaps this for an automated approach
vec <- unique(sub(" .*", "", dt$Poison))

тогда мы можем сделать:

dt |>
  mutate(grp = apply(sapply(vec, grepl, Poison), 1, function(z) which(z)[1]))
# # A tibble: 4 × 3
#   Poison            Result             grp
#   <chr>             <chr>            <int>
# 1 Arsenic           Death                1
# 2 Arsenic in Wine   Death With Class     1
# 3 Cyanide           Death                2
# 4 Cyanide and Sugar Death                2

Используйте код с осторожностью! т.е. набор данных от малого до среднего. Огромный набор данных не будет работать, поскольку adist создает матрицу n by n столбца Poison. т.е. сравнение одного элемента с остальными.

dt %>%
  mutate(group = (!adist(Poison, partial = TRUE)) %>%
           igraph::graph_from_adjacency_matrix()%>%
           igraph::components()%>%
           getElement('membership'))

# A tibble: 4 × 3
  Poison            Result           group
  <chr>             <chr>            <dbl>
1 Arsenic           Death                1
2 Arsenic in Wine   Death With Class     1
3 Cyanide           Death                2
4 Cyanide and Sugar Death                2

Если у вас вообще есть вектор необходимых групп, вы можете сделать:

vec <- c("Arsenic", "Cyanide")
transform(dt, group = max.col(-t(adist(vec, Poison, partial = TRUE))))

             Poison           Result group
1           Arsenic            Death     1
2   Arsenic in Wine Death With Class     1
3           Cyanide            Death     2
4 Cyanide and Sugar            Death     2

Если в Poison есть дублирование, вы можете использовать unique(Poison) снаружи, прежде чем использовать его внутри более крупного набора данных.

r2evans 05.04.2024 18:33

@ r2evans Это правильно. в результате чего вы в конечном итоге объедините/присоедините группы к набору данных

Onyambu 05.04.2024 18:38

Посмотрите, работает ли это с вашим набором данных. Сначала он разбивает строки, а затем сравнивает каждый элемент, чтобы увидеть, существует ли совпадение. Работаем с немного более сложным примером.

library(dplyr)

tibble(dt, grp = sapply(strsplit(dt$Poison, " "), \(x)
  paste(unique(unlist(lapply(x, \(y) 
    which(grepl(paste0("\\b", y, "\\b"), dt$Poison))))), collapse = "")))
# A tibble: 5 × 3
  Poison              Result           grp  
  <chr>               <chr>            <chr>
1 Arsenic             Death            12   
2 Arsenic A in Wine   Death With Class 125  
3 Cyanide             Death            345  
4 Cyanide and Sugar   Death            345  
5 Cyanide and Sugar A Death            3452

вывод с использованием вашего набора данных

# A tibble: 4 × 3
  Poison            Result           grp  
  <chr>             <chr>            <chr>
1 Arsenic           Death            12   
2 Arsenic in Wine   Death With Class 12   
3 Cyanide           Death            34   
4 Cyanide and Sugar Death            34

Данные

dt <- structure(list(Poison = c("Arsenic", "Arsenic A in Wine", "Cyanide", 
"Cyanide and Sugar", "Cyanide and Sugar A"), Result = c("Death", 
"Death With Class", "Death", "Death", "Death")), row.names = c(NA, 
-5L), class = c("tbl_df", "tbl", "data.frame"))

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

Похожие вопросы

Как оценить средний доход на душу населения за 10 лет в разных странах в Dataframe?
Многократная детализация Highcharter не работает с использованием разных подходов
Получить номер строки, в которой изменяется значение в столбце
Fixest::coefplot проблема с использованием «keep» и «x» для переименования переменных («Аргумент «x» должен иметь ту же длину, что и количество коэффициентов»)
Как изменить размер символа в ggplot2, если размер, форма и цвет заданы через geom_point?
Преобразование расширяемой спарклайна Plotly в график HighCharter в карте bslib с помощью javascript
Разделение столбца на основе строкового шаблона в R с использованием функций tidyverse
Можете ли вы выполнить операцию над каждой строкой кадра данных, используя Apply?
Подмножество файлов netcdf с несколькими переменными по диапазону времени
Gt() из gt по-разному раскрашивает ячейки с одинаковым содержимым?