Вопрос или проблема
У меня есть фрейм данных ниже, я хотел бы добавить столбец под названием Percentage. Упорядочить по каждой торговле. В строке CofQYr == 0 значение Percentage будет равно общей сумме по всем столбцам (с 2014 по 2024) деленной на общую сумму, где CofQYr == "Total" (с 2014 по 2024). В строке CofQYr == 1 значение Percentage будет равно общей сумме по всем столбцам (с 2014 по 2023) деленной на общую сумму, где CofQYr == "Total" (с 2014 по 2023). В строке CofQYr == 9 значение Percentage будет равно общей сумме по всем столбцам (с 2014) деленной на общую сумму, где CofQYr == "Total" только для 2014. Так что значение Percentage для 306A в CofQYr=1 = 0.0134. Структура(list(TRADE = c("306A", "306A", "306A", "306A", "306A", "306A", "306A", "306A", "306A", "306A", "306A", "306A", "307A", "307A", "307A", "307A", "307A", "307A", "307A", "307A", "307A", "307A", "307A", "307A", "307A", "308A", "308A", "308A", "308A", "308A", "308A", "308A", "308A", "308A", "308A", "308A", "308A", "308A", "308R", "308R", "308R", "308R", "308R", "308R", "308R", "308R", "308R", "308R", "308R", "308R", "309A", "309A", "309A", "309A", "309A", "309A", "309A", "309A", "309A", "309A", "309A", "309A", "309A", "309C", "309C", "309C", "309C", "309C", "309C", "309C", "309C", "309C", "309C", "313A", "313A", "313A", "313A", "313A", "313A", "313A", "313A", "313A", "313A", "313A", "313A", "313D", "313D", "313D", "313D", "313D", "313D", "313D", "313D", "313D", "313D", "313D", "313D", "339A", "339A", "339A", "339A", "339A", "339A", "339A", "339A", "339A", "339A", "339A", "339A", "339B", "339B", "339B", "339B", "339B", "339B", "339B", "339B", "339C", "339C", "339C", "339C", "339C", "339C", "339C", "427A", "427A", "427A", "427A", "427A", "427A", "427A", "427A", "427A", "427A", "427A"), CofQYr = c("0", "1", "10", "2", "3", "4", "5", "6", "7", "8", "9", "99999", "Total", "0", "1", "10", "2", "3", "4", "5", "6", "7", "8", "9", "99999", "Total", "0", "1", "10", "2", "3", "4", "5", "6", "7", "8", "9", "99999", "Total", "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "99999", "Total", "0", "1", "10", "2", "3", "4", "5", "6", "7", "8", "9", "99999", "Total", "0", "1", "2", "3", "4", "5", "6", "8", "99999", "Total", "0", "1", "10", "2", "3", "4", "5", "6", "7", "99999", "Total"), 2014
= c(77L, 60L, 2L, 80L, 136L, 248L, 105L, 55L, 55L, 36L, 5L, 510L, 1369L, 3L, 4L, 1L, 2L, 8L, 27L, 22L, 16L, 9L, 7L, 5L, 92L, 196L, 31L, 22L, 1L, 19L, 28L, 48L, 48L, 29L, 19L, 10L, 7L, 205L, 467L, 1L, 4L, 3L, 2L, 1L, 0L, 0L, 1L, 1L, 24L, 37L, 216L, 214L, 5L, 213L, 360L, 709L, 321L, 152L, 145L, 88L, 68L, 993L, 3484L, 1L, 1L, 0L, 3L, 0L, 0L, 0L, 0L, 18L, 23L, 26L, 29L, 4L, 29L, 38L, 99L, 65L, 18L, 16L, 13L, 7L, 194L, 538L, 6L, 7L, 23L, 24L, 4L, 3L, 3L, 0L, 4L, 2L, 76L, 152L, 4L, 9L, 44L, 30L, 14L, 5L, 1L, 2L, 0L, 1L, 32L, 142L, 3L, 9L, 12L, 0L, 0L, 0L, 12L, 36L, 0L, 3L, 7L, 1L, 2L, 9L, 22L, 1L, 2L, 1L, 5L, 15L, 51L, 13L, 6L, 6L, 51L, 151L), 2015
= c(46L, 30L, 0L, 45L, 113L, 175L, 98L, 83L, 57L, 20L, 6L, 484L, 1157L, 1L, 2L, 0L, 3L, 7L, 22L, 17L, 15L, 8L, 5L, 0L, 75L, 155L, 15L, 8L, 0L, 17L, 39L, 45L, 34L, 38L, 14L, 11L, 1L, 195L, 417L, 2L, 2L, 4L, 2L, 0L, 0L, 1L, 0L, 0L, 0L, 37L, 48L, 156L, 143L, 0L, 154L, 314L, 476L, 290L, 250L, 131L, 60L, 11L, 961L, 2946L, 1L, 2L, 1L, 2L, 0L, 0L, 2L, 0L, 34L, 42L, 23L, 19L, 0L, 17L, 49L, 85L, 66L, 38L, 19L, 12L, 0L, 162L, 490L, 8L, 7L, 24L, 29L, 8L, 0L, 2L, 2L, 1L, 1L, 79L, 161L, 3L, 9L, 34L, 40L, 9L, 2L, 3L, 0L, 2L, 0L, 43L, 145L, 0L, 8L, 7L, 5L, 0L, 0L, 12L, 32L, 0L, 6L, 1L, 0L, 0L, 3L, 10L, 3L, 6L, 0L, 2L, 12L, 27L, 22L, 10L, 5L, 37L, 124L), 2016
= c(30L, 40L, 0L, 40L, 60L, 135L, 168L, 91L, 51L, 9L, 0L, 555L, 1179L, 0L, 1L, 0L, 1L, 5L, 16L, 21L, 14L, 9L, 3L, 0L, 71L, 141L, 16L, 4L, 0L, 18L, 8L, 36L, 80L, 42L, 15L, 3L, 0L, 193L, 415L, 2L, 4L, 3L, 1L, 0L, 1L, 2L, 1L, 0L, 0L, 38L, 52L, 109L, 87L, 0L, 95L, 141L, 369L, 501L, 299L, 108L, 15L, 0L, 924L, 2648L, 0L, 1L, 3L, 0L, 0L, 1L, 1L, 1L, 23L, 30L, 12L, 19L, 0L, 8L, 12L, 51L, 96L, 44L, 20L, 2L, 0L, 212L, 476L, 7L, 11L, 28L, 25L, 5L, 8L, 4L, 2L, 1L, 0L, 103L, 194L, 1L, 8L, 16L, 20L, 6L, 5L, 2L, 1L, 0L, 0L, 36L, 95L, 1L, 12L, 12L, 0L, 0L, 0L, 2L, 27L, 2L, 3L, 4L, 0L, 0L, 7L, 16L, 0L, 3L, 0L, 2L, 6L, 40L, 21L, 9L, 4L, 34L, 119L), 2017
= c(25L, 18L, 0L, 12L, 46L, 200L, 176L, 67L, 15L, 0L, 0L, 550L, 1109L, 0L, 1L, 0L, 0L, 3L, 6L, 32L, 15L, 7L, 0L, 0L, 73L, 137L, 4L, 9L, 0L, 9L, 14L, 66L, 95L, 47L, 5L, 0L, 0L, 257L, 506L, 2L, 6L, 2L, 1L, 4L, 0L, 0L, 0L, 0L, 0L, 54L, 69L, 52L, 75L, 0L, 60L, 109L, 528L, 480L, 207L, 29L, 0L, 0L, 1054L, 2594L, 1L, 0L, 0L, 0L, 0L, 3L, 0L, 0L, 24L, 28L, 13L, 9L, 0L, 9L, 23L, 65L, 80L, 67L, 5L, 0L, 0L, 203L, 474L, 4L, 10L, 12L, 13L, 14L, 16L, 6L, 0L, 0L, 0L, 118L, 193L, 2L, 5L, 30L, 35L, 10L, 6L, 1L, 0L, 0L, 0L, 25L, 114L, 0L, 20L, 12L, 1L, 0L, 0L, 6L, 39L, 3L, 1L, 0L, 0L, 0L, 4L, 8L, 0L, 3L, 0L, 4L, 9L, 26L, 14L, 9L, 4L, 66L, 135L), 2018
= c(15L, 7L, 0L, 13L, 70L, 158L, 178L, 27L, 0L, 0L, 0L, 705L, 1173L, 4L, 2L, 0L, 1L, 5L, 16L, 45L, 3L, 0L, 0L, 0L, 114L, 190L, 3L, 2L, 0L, 5L, 24L, 71L, 82L, 16L, 0L, 0L, 0L, 333L, 536L, 2L, 2L, 1L, 3L, 3L, 4L, 1L, 0L, 0L, 0L, 47L, 63L, 50L, 34L, 0L, 41L, 164L, 589L, 486L, 70L, 0L, 0L, 0L, 1286L, 2720L, 2L, 0L, 0L, 1L, 1L, 1L, 0L, 0L, 28L, 33L, 8L, 4L, 0L, 5L, 24L, 77L, 108L, 9L, 0L, 0L, 0L, 271L, 506L, 3L, 3L, 5L, 17L, 22L, 10L, 3L, 0L, 0L, 0L, 126L, 189L, 1L, 2L, 31L, 29L, 15L, 2L, 1L, 0L, 0L, 0L, 48L, 129L, 6L, 17L, 20L, 1L, 2L, 0L, 3L, 49L, 8L, 1L, 0L, 1L, 0L, 8L, 18L, 1L, 3L, 0L, 1L, 14L, 71L, 34L, 8L, 0L, 104L, 236L), 2019
= c(8L, 4L, 0L, 19L, 89L, 217L, 73L, 0L, 0L, 0L, 0L, 1081L, 1491L, 1L, 2L, 0L, 1L, 3L, 18L, 7L, 0L, 0L, 0L, 0L, 135L, 167L, 2L, 1L, 0L, 9L, 45L, 84L, 27L, 0L, 0L, 0L, 0L, 473L, 641L, 0L, 0L, 2L, 5L, 1L, 1L, 0L, 0L, 0L, 0L, 40L, 49L, 15L, 26L, 0L, 54L, 170L, 628L, 181L, 0L, 0L, 0L, 0L, 2063L, 3137L, 1L, 2L, 1L, 0L, 1L, 0L, 0L, 0L, 14L, 19L, 7L, 1L, 0L, 17L, 27L, 106L, 31L, 0L, 0L, 0L, 0L, 431L, 620L, 3L, 5L, 18L, 62L, 27L, 4L, 0L, 0L, 0L, 0L, 221L, 340L, 1L, 2L, 30L, 43L, 16L, 2L, 0L, 0L, 0L, 0L, 43L, 137L, 1L, 25L, 29L, 3L, 0L, 1L, 11L, 70L, 7L, 1L, 1L, 0L, 0L, 8L, 17L, 0L, 1L, 0L, 3L, 8L, 63L, 14L, 0L, 0L, 110L, 199L), 2020
= c(3L, 4L, 0L, 14L, 50L, 38L, 0L, 0L, 0L, 0L, 0L, 791L, 900L, 0L, 0L, 0L, 0L, 4L, 1L, 0L, 0L, 0L, 0L, 0L, 85L, 90L, 1L, 0L, 0L, 2L, 14L, 9L, 0L, 0L, 0L, 0L, 0L, 322L, 348L, 2L, 1L, 2L, 2L, 0L, 0L, 0L, 0L, 0L, 0L, 28L, 35L, 10L, 22L, 0L, 45L, 126L, 110L, 0L, 0L, 0L, 0L, 0L, 1742L, 2055L, 0L, 1L, 0L, 0L, 1L, 0L, 0L, 0L, 11L, 13L, 0L, 4L, 0L, 5L, 22L, 15L, 0L, 0L, 0L, 0L, 0L, 313L, 359L, 0L, 8L, 25L, 17L, 6L, 0L, 0L, 0L, 0L, 0L, 119L, 175L, 0L, 1L, 20L, 42L, 4L, 0L, 0L, 0L, 0L, 0L, 38L, 105L, 5L, 20L, 36L, 4L, 0L, 0L, 10L, 75L, 1L, 2L, 0L, 0L, 0L, 4L, 7L, 0L, 0L, 0L, 0L, 5L, 6L, 0L, 0L, 0L, 131L, 142L), 2021
= c(2L, 6L, 0L, 15L, 14L, 0L, 0L, 0L, 0L, 0L, 0L, 1455L, 1492L, 0L, 0L, 0L, 3L, 3L, 0L, 0L, 0L, 0L, 0L, 0L, 246L, 252L, 2L, 2L, 0L, 2L, 5L, 0L, 0L, 0L, 0L, 0L, 0L, 527L, 538L, 0L, 0L, 3L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 31L, 34L, 15L, 17L, 0L, 47L, 25L, 0L, 0L, 0L, 0L, 0L, 0L, 2854L, 2958L, 4L, 0L, 2L, 0L, 0L, 0L, 0L, 0L, 35L, 41L, 0L, 0L, 0L, 6L, 10L, 0L, 0L, 0L, 0L, 0L, 0L, 469L, 485L, 3L, 22L, 32L, 9L, 0L, 0L, 0L, 0L, 0L, 0L, 183L, 249L, 3L, 3L, 13L, 16L, 0L, 0L, 0L, 0L, 0L, 0L, 95L, 130L, 7L, 12L, 55L, 1L, 0L, 0L, 26L, 101L, 3L, 8L, 0L, 0L, 0L, 4L, 15L, 0L, 1L, 0L, 3L, 0L, 0L, 0L, 0L, 0L, 226L, 230L), 2022
= c(1L, 3L, 0L, 2L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1588L, 1594L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 190L, 192L, 1L, 1L, 0L, 3L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 451L, 456L, 0L, 4L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 40L, 44L, 12L, 14L, 0L, 9L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 3091L, 3126L, 3L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 39L, 42L, 0L, 1L, 0L, 3L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 478L, 482L, 4L, 29L, 15L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 237L, 285L, 5L, 2L, 3L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 121L, 121L), 2023
= c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1400L, 1400L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 158L, 158L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 587L, 587L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 43L, 44L, 6L, 11L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 3234L, 3251L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 15L, 15L, 1L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 613L, 615L, 8L, 6L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 107L, 110L, 0L, 2L, 0L, 0L, 0L, 0L, 27L, 29L, 4L, 3L, 0L, 0L, 0L, 2L, 9L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 311L, 311L), 2024
= c(0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 1197L, 1197L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 150L, 150L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 464L, 464L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 29L, 29L, 1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 2925L, 2926L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 14L, 14L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 519L, 519L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 84L, 84L, 0L, 0L, 0L, 0L, 0L, 0L, 14L, 14L, 1L, 0L, 0L, 0L, 0L, 10L, 11L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 283L, 283L)), row.names = c(NA, -137L), class = c("tbl_df", "tbl", "data.frame")).
Возможно, я не совсем понимаю цель здесь, но подход ниже суммирует каждую строку значений в столбцах с 2014 по 2023 и затем для каждой строки TRADE|CofQYr показывает отношение суммы этой строки к соответствующей строке, где CofQYr равен "Total." Библиотека(tidyverse) df |> pivot_longer(-c(1:2)) |> summarize(value = sum(value), .by = c(TRADE, CofQYr)) |> arrange(TRADE, as.numeric(CofQYr)) |> mutate(pct = value / sum(value[CofQYr == "Total"]), .by = TRADE). Результат (первые 20 строк) TRADE CofQYr value pct
Ответ или решение
Для выполнения поставленной задачи вычисления уменьшающегося скользящего процента с фиксированным стартовым моментом в фрейме данных в R, мы можем использовать пакет dplyr
из tidyverse
. Давайте разберем данный процесс по шагам.
Задача
У вас есть фрейм данных, и вы хотите добавить новый столбец Percentage
, который будет рассчитываться следующим образом:
- Для строк, где
CofQYr == 0
, процент будет равен общей сумме по всем колонкам (с 2014 по 2024) делённой на сумму по строке, гдеCofQYr == "Total"
(также с 2014 по 2024). - Для строк, где
CofQYr == 1
, процент будет равен общей сумме по всем колонкам (с 2014 по 2023) делённой на сумму по строке, гдеCofQYr == "Total"
(также с 2014 по 2023). - Для строк, где
CofQYr == 9
, процент будет равен общей сумме по всем колонкам (только 2014) делённой на сумму по строке, гдеCofQYr == "Total"
(только 2014).
Импорт библиотек и загрузка данных
Сначала загрузим необходимые библиотеки:
library(dplyr)
library(tidyr)
Далее можно создать пример фрейма данных на основании предоставленных вами данных:
df <- structure(list(
TRADE = c("306A", "306A", ..., "427A"), # Упрощено для демонстрации
CofQYr = c("0", "1", "10", ..., "Total"),
`2014` = c(77L, 60L, ..., 77L),
`2015` = c(46L, 30L, ..., 207L), # и т.д.
`2024` = c(0L, 0L, ..., 0L)
), row.names = c(NA, -137L), class = c("tbl_df", "tbl", "data.frame"))
Рассчёт процента
Теперь создадим новый столбец Percentage
, следуя описанной логике:
# Определим книги лет
years <- 2014:2024
df <- df %>%
# Соберем данные в длинный формат
pivot_longer(cols = all_of(as.character(years)), names_to = "Year", values_to = "Value") %>%
# Суммаризация по TRADE и CofQYr
group_by(TRADE, CofQYr) %>%
summarize(TotalValue = sum(Value), .groups = 'drop') %>%
# Вычисляем процент
mutate(Percentage = case_when(
CofQYr == "Total" ~ 1,
CofQYr == "0" ~ TotalValue / TotalValue[CofQYr == "Total"],
CofQYr == "1" ~ TotalValue / sum(TotalValue[CofQYr %in% c("0", "1", "Total")]),
CofQYr == "9" ~ TotalValue / TotalValue[Year == "2014" & CofQYr == "Total"],
TRUE ~ NA_real_
)) %>%
# Проводим обратное преобразование в широкий формат
pivot_wider(names_from = Year, values_from = TotalValue) %>%
# Оставляем лишь нужные столбцы
select(TRADE, CofQYr, everything(), Percentage)
print(df)
Примечания
- Сортировка: Данный код автоматизирует группировку и агрегацию по каждому
TRADE
иCofQYr
. - Расчёт: Для каждой строки определяется процент относительно соответствующей строки с
CofQYr = "Total"
.
Заключение
Воплотив данные шаги, вы получите столбец с процентами, который будет показывать их изменение в зависимости от значения CofQYr
. Важно обращать внимание на корректность подбора индексов и работу с фильтрацией, чтобы избежать ошибок в агрегации. Настоящий пример демонстрирует основы подхода, который можно адаптировать в зависимости от специфики данных.