#r #loops #text
#r #циклы #текст
Вопрос:
Я все еще относительно новичок в R, и я получил эту задачу.
У меня есть таблица (код ниже), в которой первый столбец состоит из имен менеджеров и проектов, которые у них есть. Всегда после имени менеджера (например, «Том Джонс») перечислены его проекты (например, «019200 [ytb] ppp») и другие виды деятельности (например, «Управление рисками»). Другие столбцы представляют рабочие часы ( capacity
) и фактические рабочие часы ( actual_hours
), которые менеджер потратил на проекты.
[Обновленный фрейм данных]
df <- data.frame('Name'=c('Tom Jones', '0192000 [ytb] ppp', 'I-2020020 [BBB] Adm Valid', 'TENT DATZ 20204001 [ASS]','Risk Management', 'Andrea Jose Casteno','2040044 [Amaas] HHHHJ', '0291111 [inezzz] plmi', 'Training', 'Gerard van der Dike', '20200222 20203333 [Ttt ID/ZZ] HHH SSS DD Dpp', 'Other' , 'R-20204444 [Res] Phhh Top SAA', 'Bill Gatea', 'Leave','2019xxxx [zzz] Aap ZZ'), 'capacity' = c(40,0,0,0,0,36,0,0,0,40,0,0,0,38,0,0), 'actual_hours' = c(44,12,2,20,10,40,30,0,10,43,20,10,13,38,20,18))
Список менеджеров:
manager_names= c('Tom Jones', 'Andrea Jose Casteno', 'Gerard van der Dike', 'Bill Gatea')
Мне нужно преобразовать эту таблицу в вывод ниже (рисунок ниже). Для каждого менеджера, который работал больше, чем его возможности ( actual_hours
> capacity
), мне нужно создать строку в новой таблице. Первым столбцом должно быть имя менеджера. Второй и третий столбцы показывают его capacity
и actual_hours
. В четвертом столбце должны быть представлены краткие названия проектов, над которыми работал manger (исключить проекты с 0 == actual_hours
). Короткие названия проектов необходимо вычесть из Name
столбца — они заключены в квадратные скобки (например, BBB)
На данный момент я попробовал приведенные ниже строки, но я застрял в том, как вычесть информацию о проектах (четвертый столбец в выходных данных). Вероятно, необходим цикл, использующий список имен менеджеров.
z=(which(df$actual_hours > df$capacity))
output_df=df[z,c("Name","capacity","actual_hours")]
y=which(output_df$capacity==0, arr.ind=TRUE)
newdf <- output_df[-y, ]
Заранее спасибо за вашу помощь!
Ответ №1:
Вот базовый параметр R
do.call(
rbind,
lapply(
split(df, cumsum(grepl("manager\d ", df$Name))),
function(v) {
if (v$capacity[1] <= v$actual_hours[1]) {
cbind(v[1, ], projects = toString(gsub(".*\[(\w )\].*", "\1", v$Name[-1])))
} else {
NULL
}
}
)
)
что дает
Name capacity actual_hours projects
1 manager1 40 44 ytb, ytv, COM
2 manager2 36 40 TYU, inezzz
3 manager3 40 43 TYUKKK, ine
Комментарии:
1. Большое спасибо за ваш ответ, Томас. На самом деле, реальные данные в столбце «Имя» содержат имя и фамилию менеджера, поэтому шаблона «менеджер» нет. В функции я вижу, что это скорее связано с «емкостью» (т. Е. Если «емкость» равна = 0, то …) Кроме того, проекты, у которых нулевые часы в ‘actual_hours’, не должны быть перечислены в ‘projects’. У вас есть какие-то предложения по этому поводу? Заранее спасибо
Ответ №2:
Вот вариант с tidyverse
. После создания столбца группировки путем взятия совокупной суммы логического вектора, т.Е. Где подстрока ‘manager’ находится в ‘Name’, затем summarise
путем paste
ввода извлеченных слов в квадратные скобки, а также получения значений столбцов first
строки с помощью across
library(dplyr)
library(stringr)
df %>%
group_by(grp = cumsum(str_detect(Name, 'manager'))) %>%
summarise(projects = str_c(str_extract(Name[-1],
"(?<=\[)\w "), collapse="; "),
across(c(Name, capacity, actual_hours), first), .groups = 'drop') %>%
select(names(df), 'projects')
-вывод
# A tibble: 3 x 4
# Name capacity actual_hours projects
# <chr> <dbl> <dbl> <chr>
#1 manager1 40 44 ytb; ytv; COM
#2 manager2 36 40 TYU; inezzz
#3 manager3 40 43 TYUKKK; ine
Комментарии:
1. Большое спасибо за ваш ответ Akrun. Я уже упоминал в решении Thomas, что на самом деле реальные данные в столбце «Имя» содержат имя и фамилию менеджера, поэтому шаблона «менеджер» нет. В коде я вижу, что это скорее связано с «емкостью» (т. Е. Если «емкость» равна = 0, то …) Кроме того, проекты, у которых нулевые часы в ‘actual_hours’, не должны быть перечислены в ‘projects’. Есть ли у вас какие-либо предложения в этом случае? Заранее спасибо
2. @Просто есть ли в данных какой-либо шаблон, который мы можем использовать
3. @JustT если вы измените шаблон на
cumsum(str_detect(Name, '^[A-Za-z]))
, это сработает? Я нахожу цифры, начинающиеся в других строках4. Имена структурированы так, как вы описали, например, «Том Джонс», но также и «Бен ван дер Дайк». Названия проектов иногда начинаются с цифр, иногда с буквы цифры, затем в [ ] есть краткое название проекта и полное название проекта буквами — как короткие, так и полные названия проектов содержат заглавные и строчные буквы (иногда только заглавные), например ‘11101 [Nama] Naa Maa’ или ‘R-2000[Hor] Prop Hut’ . Мне также нужно исключить проекты, которые имеют нулевые часы в «actual_hours». Надеюсь, это поможет 🙂
5. Я мог бы также создать список с именами менеджеров, но я не уверен, как тогда адаптировать код…