Вычислите процентное изменение между несколькими столбцами фрейма данных

#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
 

Итак, это согласовано.