#r #dplyr #group-by #tidyverse
Вопрос:
У меня есть df, который смотрит только на 1 идентификатор с соответствующими активами:
ID | Asset | CONF_1 | CONF_2 | CONF_3 | 1 A PERFECT HIGH LOW 1 B PERFECT LOW LOW 1 C LOW HIGH VERY LOW 1 D NA MEDIUM MEDIUM 1 E MEDIUM MEDIUM PERFECT 1 F MEDIUM VERY LOW NA 1 G VERY LOW VERY LOW VERY LOW 1 H NA PERFECT HIGH
Цель состоит в том, чтобы реорганизовать df, чтобы я мог разбить % каждого уровня уверенности (ИДЕАЛЬНЫЙ, ВЫСОКИЙ, СРЕДНИЙ И Т. Д.) С учетом каждого идентификатора и 3 полей Conf.
Желаемый результат
ID | CONFIDENCE | CONF_1 % | CONF_2 % | CONF_3 % 1 PERFECT 25 % 12.5 % 12.5 % 1 HIGH 0 25 % 12.5 % 1 MEDIUM 25 % 25 % 12.5 % 1 LOW 12.5 % 12.5 % 25 % 1 VERY LOW 12.5 % 25 % 25 % 1 NA 25 % 0 12.5 %
Комментарии:
1. Я полагаю, что так @akrun — знаменатель равен 8, и я просто подсчитал, сколько раз каждый уровень конфронтации происходил из 8
2. Пожалуйста, проверьте решение, которое я опубликовал
Ответ №1:
Сгруппированные по столбцам «ID», summarise
across
«CONF», получите счетчик частот table
в factor
столбце с levels
указанным в порядке и найдите proportions
library(dplyr) df1 %gt;% group_by(ID) %gt;% summarise(lvls = c("PERFECT", "HIGH", "MEDIUM", "LOW", "VERY LOW", NA), across(starts_with("CONF"), ~ 100 * proportions(table(factor(., levels = na.omit(lvls)), useNA = "always"))), .groups = 'drop') %gt;% rename(CONFIDENCE = lvls)
-выход
# A tibble: 6 × 5 ID CONFIDENCE CONF_1 CONF_2 CONF_3 lt;intgt; lt;chrgt; lt;tablegt; lt;tablegt; lt;tablegt; 1 1 PERFECT 25.0 12.5 12.5 2 1 HIGH 0.0 25.0 12.5 3 1 MEDIUM 25.0 25.0 12.5 4 1 LOW 12.5 12.5 25.0 5 1 VERY LOW 12.5 25.0 25.0 6 1 lt;NAgt; 25.0 0.0 12.5
—
Или другой вариант-изменить форму в «длинный» формат с pivot_longer
помощью , выполните count
и измените форму обратно в «широкий» формат с помощью pivot_wider
library(tidyr) df1 %gt;% select(-Asset) %gt;% pivot_longer(cols = starts_with("CONF"), values_to = 'CONFIDENCE') %gt;% count(ID, name, CONFIDENCE) %gt;% group_by(ID, name) %gt;% mutate(n = 100 *n/sum(n) ) %gt;% ungroup %gt;% pivot_wider(names_from = name, values_from = n, values_fill = 0)
-выход
# A tibble: 6 × 5 ID CONFIDENCE CONF_1 CONF_2 CONF_3 lt;intgt; lt;chrgt; lt;dblgt; lt;dblgt; lt;dblgt; 1 1 LOW 12.5 12.5 25 2 1 MEDIUM 25 25 12.5 3 1 PERFECT 25 12.5 12.5 4 1 VERY LOW 12.5 25 25 5 1 lt;NAgt; 25 0 12.5 6 1 HIGH 0 25 12.5
данные
df1 lt;- structure(list(ID = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), Asset = c("A", "B", "C", "D", "E", "F", "G", "H"), CONF_1 = c("PERFECT", "PERFECT", "LOW", NA, "MEDIUM", "MEDIUM", "VERY LOW", NA), CONF_2 = c("HIGH", "LOW", "HIGH", "MEDIUM", "MEDIUM", "VERY LOW", "VERY LOW", "PERFECT" ), CONF_3 = c("LOW", "LOW", "VERY LOW", "MEDIUM", "PERFECT", NA, "VERY LOW", "HIGH")), class = "data.frame", row.names = c(NA, -8L))
Комментарии:
1. Блестяще — я начал использовать pivot_wider, но это фантастика. Спасибо.
2. есть ли способ заказать по идентификатору, а затем по уровням ДОВЕРИЯ? Таким образом, каждый идентификатор имеет одинаковый порядок уровней достоверности, и он сбрасывается для каждого идентификатора.
3. @Dinho Вы можете указать
arrange(ID, factor(CONFIDENCE, levels = c("PERFECT", "HIGH", "MEDIUM", "LOW", "VERY LOW")))
промежуток между
Ответ №2:
Решение, основанное на reshape2
:
library(dplyr) library(reshape2) df %gt;% melt(id.vars="ID", measure.vars=paste0("CONF_",1:3), variable.name="X") %gt;% dcast(ID X ~ value, fun.aggregate = length) %gt;% melt(id.vars=c("ID","X"), measure.vars=3:ncol(.) ) %gt;% dcast(ID variable ~ X) %gt;% group_by(ID) %gt;% mutate(across(starts_with("CONF_"), ~ .x*100 /sum(.x))) %gt;% rename(CONFIDENCE=variable) %gt;% arrange(ID,CONFIDENCE)