Выбор неслучайно из столбца имен и описаний

#r #dplyr

Вопрос:

У меня есть a data.frame (df) , который содержит колонку студентов projects , основанную на бетоне, мостах или воде (некоторые включают несколько терминов), каждому проекту присваивается a professor , но мне нужно выбрать второй маркер для этого проекта. Поэтому я хотел бы сопоставить имя профессора, основываясь на том факте, что оба их проекта содержат слова «бетон», «мосты» или «вода».

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

 dflt;-data.frame(professor=c("Hellen", "Ben","Ethel", "Jim","Connor", "Juan","Lucy"), project=c("Bridges with stone", "Waterways","Concrete with steel","Structure of concrete bridges","Public health and water","Masonry of bridges","3D concrete"))  

Потенциальное решение будет выглядеть следующим образом:

 data.frame(professor=c("Hellen", "Ben","Ethel", "Jim","Connor", "Juan","Lucy"), project=c("Bridges with stone", "Waterways","Concrete with steel","Structure of concrete bridges","Public health and water","Masonry of bridges","3D concrete"),second_Marker=c("Juan","Connor","Jim","Lucy","Ben","Hellen","Ethel"))  

введите описание изображения здесь

Комментарии:

1. может ли каждый профессор быть вторым маркером только один раз?

2. Хороший вопрос. Нет, они могут появляться столько раз, сколько возможно случайным образом.

3. @RonakShah Спасибо тебе. Я хотел бы сопоставить их в зависимости от того, есть ли в названии проекта, который предлагает профессор, мосты. т. е. Хеллен и Хуан оба работают над мостами, чтобы понять проект друг друга. В то время как Бен работает с водой и не может понять работу Хеллена, так что они не подошли бы друг другу.

4. @RonakShah ой! Это моя ошибка, спасибо, что заметили это — я исправлю ее в описании.

5. @RonakShah рамка данных правильная, картинка была неправильной, извините за путаницу

Ответ №1:

Вот один из способов сделать это —

Извлеките keyword значение из проекта с помощью str_extract , для каждого keyword получите случайное совпадение, которое не является именем профессора.

 library(tidyverse)  df %gt;%  group_by(keyword = tolower(str_extract(project,   regex('(concrete|bridges|water)', ignore_case = TRUE)))) %gt;%  mutate(second_Marker = map_chr(professor,   ~sample(setdiff(professor, .x), 1))) %gt;%  ungroup  # professor project keyword second_Marker # lt;chrgt; lt;chrgt; lt;chrgt; lt;chrgt;  #1 Hellen Bridges with stone bridges Juan  #2 Ben Waterways water Connor  #3 Ethel Concrete with steel concrete Jim  #4 Jim Structure of concrete bridges concrete Lucy  #5 Connor Public health and water water Ben  #6 Juan Masonry of bridges bridges Hellen  #7 Lucy 3D concrete concrete Ethel   

Комментарии:

1. Большое вам спасибо за ваше решение. мой R говорит, что объект x «регулярное выражение» не найден. Я уверен, что видел эту ошибку раньше, но ничего не могу найти в Google. Вы видели это раньше?

2. regex функция доступна в stringr упаковке. Попробуйте использовать stringr::regex

3. Действительно, большое вам спасибо. Это прекрасно работает. Я понимаю, что не все названия проектов содержат их, но что-то подобное, которое может появиться только один раз. Так что у этого будет своя категория. Возможно ли «ослабить» ограничение и поместить несколько слов в одну и ту же категорию. Например, бетон И мосты-это одна категория, например?

4. Я не уверен, что понимаю, но вы можете использовать str_extract_all для извлечения всех ключевых слов в проекте. str_extract даст только один (первый) шаблон на выходе.

5. Это не так. Первый group_by гарантирует, что данные передаются только по одному и тому же ключевому mutate слову, поэтому нам не нужно беспокоиться о ключевых словах на этом mutate шаге.

Ответ №2:

Использование dplyr и stringr :

Данные:

 dflt;-data.frame(professor=c("Hellen", "Ben","Ethel", "Jim","Connor", "Juan","Lucy"), project=c("Bridges with stone", "Waterways","Concrete with steel","Structure of concrete bridges","Public health and water","Masonry of bridges","3D concrete"))  

Код:

 df2 lt;- df %gt;%   mutate(project = str_to_lower(project)) %gt;%   mutate(indicator = NA) %gt;%   mutate(indicator = ifelse(str_detect(project,  "water"),  "water",  indicator)) %gt;%   mutate(indicator = ifelse(str_detect(project,  "bridges"),  "bridges",  indicator)) %gt;%   mutate(indicator = ifelse(str_detect(project,  "concrete"),  "concrete",  indicator))   prof lt;- df2 %gt;%   select(indicator, professor) %gt;%   rename(second_Marker = professor)  left_join(df2,  prof,  by = "indicator") %gt;%   filter(professor != second_Marker) %gt;%   group_by(professor, project) %gt;%   slice_sample(n = 1) %gt;%   select(-indicator) %gt;%  ungroup()  

Выход:

 # A tibble: 7 x 3 # Groups: professor, project [7]  professor project second_Marker  lt;chrgt; lt;chrgt; lt;chrgt;  1 Ben waterways Connor  2 Connor public health and water Ben  3 Ethel concrete with steel Lucy  4 Hellen bridges with stone Juan  5 Jim structure of concrete bridges Lucy  6 Juan masonry of bridges Hellen  7 Lucy 3d concrete Jim   

Как slice_sample и в случайном случае, при каждом запуске кода вы будете получать еще один второй маркер

Редактировать:

Теперь, если вам нужна уникальная категория для мостов или бетона, | оператор может обработать ее с помощью почти того же кода:

 df2 lt;- df %gt;%   mutate(project = str_to_lower(project)) %gt;%   mutate(indicator = NA) %gt;%   mutate(indicator = ifelse(str_detect(project,  "water"),  "water",  indicator)) %gt;%  mutate(indicator = ifelse(str_detect(project,  "concrete") | str_detect(project,  "bridges"),  "concrete_or_bridges",  indicator))  prof lt;- df2 %gt;%   select(indicator, professor) %gt;%   rename(second_Marker = professor)  left_join(df2,  prof,  by = "indicator") %gt;%   filter(professor != second_Marker) %gt;%   group_by(professor, project) %gt;%   slice_sample(n = 1) %gt;%   select(-indicator) %gt;%  ungroup()  

Когда project содержит concrete ИЛИ ( | ) bridges , он считает, что проект относится к concrete_or_bridges категории.

Таким образом, один из возможных выходов:

 professor project second_Marker  lt;chrgt; lt;chrgt; lt;chrgt;  1 Ben waterways Connor  2 Connor public health and water Ben  3 Ethel concrete with steel Lucy  4 Hellen bridges with stone Ethel  5 Jim structure of concrete bridges Ethel  6 Juan masonry of bridges Lucy  7 Lucy 3d concrete Juan   

Как вы можете видеть, Этель станет вторым маркером проекта «Хеллен», даже если проект «Этель» посвящен бетону, а проект «Хеллен» — мостам

Комментарии:

1. Действительно, большое вам спасибо за вашу помощь и решение этой проблемы. Мне нравится, что это гибко, чтобы включить разные слова в одну и ту же категорию. Например, мосты И сооружения все еще могут быть мостами. А ты как думаешь?

2. @HCAI Я не уверен, что пойму это. Вы хотите, чтобы мосты И сооружения были категорией, когда они встречались в проекте (т. е. «конструкция бетонных мостов» -gt; новая категория), или вы хотите категорию, когда встречается один из двух (т. е. «мосты из камня» или «3d бетон» -gt;gt; новая категория)?

3. Спасибо, я имею в виду, что если в нем есть сооружения или мосты, то это та же категория

4. @HCAI, пожалуйста, ознакомьтесь с правкой.