Как изменить фреймворк данных, используя ссылки на динамические измерения?

Предположим, мы начинаем с кадра данных data, показанного ниже, с кодом генерации сразу под ним:

> data
   To A  B  C
1   A 1  3  5
2   B 2  4  6
3   C 4  5  7
4 Sum 7 12 18
   
library(dplyr)
data <- 
   data.frame(
     To = c("A","B","C"),
     A = c(1,2,4),
     B = c(3,4,5),
     C = c(5,6,7)
   ) %>% 
   bind_rows(summarise_all(., ~(if(is.numeric(.)) sum(.) else "Sum")))

Я запускал следующий фрагмент кода, чтобы изменить значения в фрейме данных, очень похожие на проценты (каждая ячейка рассчитывается как% от соответствующего столбца «Сумма»):

data %>% mutate(across(-1, ~ ./.[To == "Sum"]))

Предоставление правильного вывода:

> data 
   To         A         B         C
1   A 0.1428571 0.2500000 0.2777778
2   B 0.2857143 0.3333333 0.3333333
3   C 0.5714286 0.4166667 0.3888889
4 Sum 1.0000000 1.0000000 1.0000000

Как заменить делитель [To == "Sum"] в mutate(across...)) динамической (возможно, числовой) ссылкой на последнюю строку фрейма данных? В более полном коде это развертывается в фрейме данных динамически и реактивно расширяется/сокращается на основе пользовательского ввода в Shiny, а имена заголовков столбцов также изменяются динамически, поэтому фиксированная ссылка на имя заголовка «Кому» в этом примере не оптимальна.

Краткое объяснение тоже было бы полезно, так что мне не нужно постоянно приходить к корыту в поисках решений.

Ответ @akrun правильный, но в R не очень идиоматично иметь строку суммы во фрейме данных, поэтому в конечном итоге вы сделаете что-то немного неловкое. Было бы лучше просто иметь фрейм данных значений, создать отдельный фрейм данных сумм для использования в операциях, и если вам нужно представить их в таблице, то привязать их, но только для представления, а не для расчета.

SamR 17.05.2022 19:59

@SamR Более простой вариант janitor::adorn_totals(data)

akrun 17.05.2022 19:59
Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Стилизация и валидация html-формы без использования JavaScript (только HTML/CSS)
Будучи разработчиком веб-приложений, легко впасть в заблуждение, считая, что приложение без JavaScript не имеет права на жизнь. Нам становится удобно...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Что такое cURL в PHP? Встроенные функции и пример GET запроса
Клиент для URL-адресов, cURL, позволяет взаимодействовать с множеством различных серверов по множеству различных протоколов с синтаксисом URL.
Четыре эффективных способа центрирования блочных элементов в CSS
Четыре эффективных способа центрирования блочных элементов в CSS
У каждого из нас бывали случаи, когда нам нужно отцентрировать блочный элемент, но мы не знаем, как это сделать. Даже если мы реализуем какой-то...
1
2
25
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Ответ принят как подходящий

Мы можем использовать функцию last, чтобы вернуть последнее значение столбца. Кроме того, есть еще один вариант с nth, где мы можем получить значение столбца на основе более общего индекса, т. е. nth(., 2) возвращает второе значение.

library(dplyr)
data %>% 
   mutate(across(-1, ~ ./last(.)))

-выход

 To         A         B         C
1   A 0.1428571 0.2500000 0.2777778
2   B 0.2857143 0.3333333 0.3333333
3   C 0.5714286 0.4166667 0.3888889
4 Sum 1.0000000 1.0000000 1.0000000

Это было слишком просто для тебя, Акрун! Вы заслуживаете перерыва время от времени с такими младшими вопросами! Спасибо за объяснение. В ближайшее время мне нужно будет проработать некоторые вводные материалы для dplyr и data.table.

Curious Jorge - user9788072 17.05.2022 19:58

Слишком просто для мастера Акруна!

TarJae 17.05.2022 20:05

в Base R вы можете сделать что-то вроде:

addmargins(prop.table(as.matrix(data.frame(data, row.names = 1)),2),1)

            A         B         C
A   0.1428571 0.2500000 0.2777778
B   0.2857143 0.3333333 0.3333333
C   0.5714286 0.4166667 0.3888889
Sum 1.0000000 1.0000000 1.0000000

Попробуйте это: это более или менее то, что уже представляет akrun:

library(dplyr)

data <- 
  data.frame(
    To = c("A","B","C"),
    A = c(1,2,4),
    B = c(3,4,5),
    C = c(5,6,7)
  ) %>% 
  mutate(across(-1, ~ ./sum(.))) %>% 
  bind_rows(summarise_all(., ~(if(is.numeric(.)) sum(.) else "Sum")))
   To         A         B         C
1   A 0.1428571 0.2500000 0.2777778
2   B 0.2857143 0.3333333 0.3333333
3   C 0.5714286 0.4166667 0.3888889
4 Sum 1.0000000 1.0000000 1.0000000

Другие вопросы по теме