Как получить общую сумму на основе определенных столбцов, содержащих одно и то же значение

В кадре данных есть столбцы code1, code2, code3 и т. д., в которых хранятся коды. Для каждого кода есть столбец с количеством использованных дней days_used1, days_used2, days_used3 и т. д. Я хочу получить фрейм данных, включающий столбец для каждого кода, в котором дни_использованы суммированы для каждого из значений в code.

data.frame(ID = c(1, 2, 3, 4, 5,6),
            code1 = c('D', 'D', 'C', 'A', 'G', "A"),
           quantity1 = c(10, 10, 15, 30, 20, 10),
           dose1 = c(5, 5, 15, 0.5, 2, 10), 
           days_used1 = c(NA, NA, 90, 63, 20, 50),
           code2 = c('A', 'H', 'D', 'G', 'A', "A"),
           quantity2 = c(5, 10, 10, 20, 20, 5),
           dose2 = c(0.1, 15, 15, 7, 5, 12), 
           days_used2 = c(15, NA, NA, 50, 20, 10),
           code3 = c('A', 'H', 'C', 'A', 'D', "D"),
           quantity3 = c(10, 10, 15, 30, 20, 10),
           dose3 = c(5, 5, 15, 0.5, 2, 10), 
           days_used3 = c(15, NA, NA, 50, 20, 10)
 )

Итак, я хочу, чтобы фрейм данных выглядел так:

data.frame(ID = c(1, 2, 3, 4, 5),
                  A= c(30, 0, 0, 20, 60),
                  D = c(0, 0, 0, 0, 20, 10),
                  C= c(0, 0, 90, 0, 20, 10),
                  G= c(0, 0, 0, 50, 20, 0),
                  H= c(0, 0, 0, 0, 0)
)

Я действительно не знаю, как мне это сделать. Я пробовал что-то вроде примера ниже, но это явно не работает.

ifelse(test[paste0("code",c(1:3))] == "A",
         sum(test[paste0("code",c(1:3)) == "A"]+1), 
         0)
     code1 code2 code3
[1,]     0     0     0
[2,]     0     0     0
[3,]     0     0     0
[4,]     0     0     0
[5,]     0     0     0
[6,]     0     0     0
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
62
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Мы могли бы выполнить поворот, разделив имена столбцов по последнему символу, затем посчитать по идентификатору и коду и распределить это:

library(tidyverse)
df |>
  pivot_longer(-ID, names_to = c(".value", "obs"), names_sep = -1) |>
  count(ID, code, wt = days_used) |>
  pivot_wider(names_from = code, values_from = n, values_fill = 0)
  

Результат

# A tibble: 6 × 6
     ID     A     D     H     C     G
  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1     1    30     0     0     0     0
2     2     0     0     0     0     0
3     3     0     0     0    90     0
4     4   113     0     0     0    50
5     5    20    20     0     0    20
6     6    60    10     0     0     0

(подробнее объяснение)

После первого шага поворота мы получим

# A tibble: 18 × 4
      ID obs   code  days_used
   <dbl> <chr> <chr>     <dbl>
 1     1 1     D            NA
 2     1 2     A            15
 3     1 3     A            15
 4     2 1     D            NA
 5     2 2     H            NA
 6     2 3     H            NA
 7     3 1     C            90
 8     3 2     D            NA
 9     3 3     C            NA
10     4 1     A            63
11     4 2     G            50
12     4 3     A            50
13     5 1     G            20
14     5 2     A            20
15     5 3     D            20
16     6 1     A            50
17     6 2     A            10
18     6 3     D            10

Затем мы можем суммировать по идентификатору и коду. (В качестве альтернативы мы могли бы использовать ... |> summarize(n = sum(days_used), .by = c(ID, code)), но я предпочитаю синтаксис count(), когда мы просто суммируем группы.

# A tibble: 13 × 3
      ID code      n
   <dbl> <chr> <dbl>
 1     1 A        30
 2     1 D         0
 3     2 D         0
 4     2 H         0
 5     3 C        90
 6     3 D         0
 7     4 A       113
 8     4 G        50
 9     5 A        20
10     5 D        20
11     5 G        20
12     6 A        60
13     6 D        10

Между моим фреймом данных есть еще несколько столбцов, которые можно игнорировать (см. Редактирование). Также различается структура столбцов. Для первого шага я попробовал data |> pivot_longer(cols=c(p_id, starts_with("code"), starts_with("days_used")), values_transform = list(p_id = as.character, code= as.character, days_used = as.numeric)), но все равно получаю Can't combine p_id <character> and days_used1 <double>

Noa 24.04.2024 10:05
Ответ принят как подходящий
library(data.table)

dcast(
      melt(setDT(test), id=1L,
           measure=patterns("^code", "^days"),
           value.name=c("Code", "Days"))[,
            .(sumDays = sum(Days, na.rm = T)), 
            .(ID, Code)],
      ID  ~ Code, value.var = c("sumDays"), fill = 0)

#>    ID   A  C  D  G H
#> 1:  1  30  0  0  0 0
#> 2:  2   0  0  0  0 0
#> 3:  3   0 90  0  0 0
#> 4:  4 113  0  0 50 0
#> 5:  5  20  0 20 20 0
#> 6:  6  60  0 10  0 0

Created on 2024-04-23 with reprex v2.0.2

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

Установите значение матрицы равным 0, если имена строк и столбцов начинаются с одного и того же префикса
Как создать столбец фрейма данных, который представляет собой список из нескольких отдельных записей столбца?
Создать список уникальных комбинаций наборов данных для удаления дубликатов
Применить множественную функцию суммирования к столбцам: summarise_all: объект «список» нельзя заставить ввести «двойной»
Суперсложные манипуляции с наборами данных
Как я могу заполнить недостающие строки столбца данных, используя среднее значение другого столбца?
Функция DataFrame groupby, возвращающая кортеж из столбца вместо значения
Переместить информацию определенного столбца в новую строку под текущей строкой
Суммируйте значения конкретных уровней факторов по каждой группе в фрейме данных
Объединить два кадра данных с разными заголовками