В кадре данных есть столбцы 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





Мы могли бы выполнить поворот, разделив имена столбцов по последнему символу, затем посчитать по идентификатору и коду и распределить это:
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
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
Между моим фреймом данных есть еще несколько столбцов, которые можно игнорировать (см. Редактирование). Также различается структура столбцов. Для первого шага я попробовал
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>