#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, пожалуйста, ознакомьтесь с правкой.