#r #function #dplyr #difference
Вопрос:
У меня есть фрейм данных следующим образом :
id <- c(1, 2, 3, 4, 5)
week1 <- c(234,567456, 134123, 13412421, 2345245)
week2 <- c(4234,5123456, 454123, 12342421, 8394545)
week3 <- c(1234, 234124, 12348, 9348522, 134534)
data <- data.frame(id, week1, week2, week3)
Я хотел бы найти процентное изменение между неделей 1 и неделей 2, а затем неделей 2 и неделей 3 и т. Д. (Мой фрейм данных намного больше и содержит около 27 столбцов).
Я пытался:
data$change1 <- (data$week2-data$week1)*100/data$week1
Однако это было бы обширно с большим набором данных.
Комментарии:
1. Математический оператор имеет методы для
data.frame
s в R;(data[-(1:2)] - data[-c(1, ncol(data))]) * 100 / data[-c(1, ncol(data))]
2. Когда я пробую это на своем большем наборе данных, я получаю сообщение об ошибке с указанием
Error in Ops.data.frame(table_names[-(1:7)], table_names[-c(1, 27)]) : ‘-’ only defined for equally-sized data frames
любых предложений относительно того, почему это происходит? Мой df составляет 12714 строк на 27 колов3. Я пытаюсь найти процентное изменение от столбцов 7 до 27 (конец)
4. В первом подмножестве (
table_names[-(1:7)]
) вы удаляете все столбцы, не относящиеся к данным1:6
(), и первый столбец данных (7
). Во втором подмножестве (table_names[-c(1, 27)]
) вы удаляете только первый и последний столбцы. Таким образом, два подмножества имеют разное количество столбцов, отсюда (информативное) сообщение: »-
определено только для фреймов данных одинакового размера». Вам нужно настроить второе подмножество так, чтобы удалить последний столбец и все столбцы, не содержащие данных. Я оставляю это на ваше усмотрение. Овации5. @JaneMiller если приведенный ниже ответ поможет, пожалуйста, примите ответ, чтобы он больше не отображался как неотвеченный, и если вы считаете, что он полезен, вы даже можете проголосовать за него. Если он не ответил на ваш запрос, не стесняйтесь объяснять оставшуюся проблему. Возможно, вы захотите сделать то же самое для любого другого заданного вами вопроса, на который был дан ответ.
Ответ №1:
Попробуйте сделать следующее:
library(tidyverse)
df <- gather(df, key='week', value='value', -id)
df$week <- as.integer(as.character((gsub('week', '', df$week))))
df %>% group_by(id) %>% arrange(week) %>% mutate(perc_change = (value-lag(value,1))/lag(value,1)*100)
# A tibble: 15 x 4
# Groups: id [5]
id week value perc_change
<dbl> <int> <dbl> <dbl>
1 1 1 234 NA
2 2 1 567456 NA
3 3 1 134123 NA
4 4 1 13412421 NA
5 5 1 2345245 NA
6 1 2 4234 1709.
7 2 2 5123456 803.
8 3 2 454123 239.
9 4 2 12342421 -7.98
10 5 2 8394545 258.
11 1 3 1234 -70.9
12 2 3 234124 -95.4
13 3 3 12348 -97.3
14 4 3 9348522 -24.3
15 5 3 134534 -98.4
Это работает достаточно хорошо, но предполагает, что наблюдение проводится каждую неделю, иначе ваше процентное изменение будет основываться на последней доступной неделе (поэтому, если отсутствует неделя 3, значение для недели 4 будет равно изменению недели за неделю со 2-й неделей в качестве основы).
(Правка: заменено substr
на gsub
)
Проверка смысла:
Для строки 6 вы видите идентификатор 1. Это 2-я неделя со значением 4234. На 1-й неделе идентификатор 1 имел значение 234. Разница в том, что
(4234-234)/234
[1] 17.09402
Итак, это согласовано.