Разделите на значение для определенного фактора с учетом времени (dplyr, data.table) - PullRequest
1 голос
/ 17 октября 2019

У меня есть данные в длинном формате, подобном этому:

library(tidyverse)

df <- data.frame(
  projection1 = c(2,4,3),
  projection2 = c(3,1,4),
  historical_data = c(2,3,4),
  time = c(1,2,3)
) %>% 
  as_tibble() %>% 
  gather(key = key, value = val, projection1:historical_data) %>% 
  mutate(key = key %>% factor())

Затем данные выглядят так:

# A tibble: 9 x 3
   time key               val
  <dbl> <fct>           <dbl>
1     1 projection1         2
2     2 projection1         4
3     3 projection1         3
4     1 projection2         3
5     2 projection2         1
6     3 projection2         4
7     1 historical_data     2
8     2 historical_data     3
9     3 historical_data     4

Теперь я хотел бы рассчитать относительную разницу каждый годзначения из projection1 и projection2 относительно исторического_данных. Таким образом, я хотел бы, чтобы мои данные заканчивались следующим образом:

# A tibble: 9 x 4
   time key               val pct_diff
  <dbl> <fct>           <dbl>    <dbl>
1     1 projection1         2    1    
2     2 projection1         4    1.33 
3     3 projection1         3    0.75 
4     1 projection2         3    1.5  
5     2 projection2         1    0.333
6     3 projection2         4    1    
7     1 historical_data     2    1    
8     2 historical_data     3    1    
9     3 historical_data     4    1

Я всегда заканчиваю разделением и слиянием, чтобы получить новые, казалось бы, избыточные столбцы, содержащие значения, которые уже находятся в текущем dataframe / tibbleсделать расчеты. Мне было интересно, если есть элегантное dplyr или, возможно, data.table решение для этого? Или, возможно, вы сможете задать мне вопрос, на который уже дан ответ. Сам не сталкивался.

Спасибо

Ответы [ 2 ]

2 голосов
/ 17 октября 2019

Вот возможный подход с использованием data.table и использованием комментария jangorecki с использованием == вместо более медленного grep:

DT[, ratio := 1][key!="historical_data", 
    ratio := DT[key=="historical_data"][.SD, on=.(time), i.val/x.val]]

Или более коротким, но, вероятно, более медленным:

DT[, ratio := DT[key=="historical_data"][.SD, on=.(time), i.val/x.val]]

вывод:

   time             key val     ratio
1:    1     projection1   2 1.0000000
2:    2     projection1   4 1.3333333
3:    3     projection1   3 0.7500000
4:    1     projection2   3 1.5000000
5:    2     projection2   1 0.3333333
6:    3     projection2   4 1.0000000
7:    1 historical_data   2 1.0000000
8:    2 historical_data   3 1.0000000
9:    3 historical_data   4 1.0000000

данные:

library(data.table)
DT <- fread("time key val
1 projection1         2
2 projection1         4
3 projection1         3
1 projection2         3
2 projection2         1
3 projection2         4
1 historical_data     2
2 historical_data     3
3 historical_data     4")
0 голосов
/ 17 октября 2019

Вот один простой способ использования групп:

 data.frame(
  projection1 = c(2,4,3),
  projection2 = c(3,1,4),
  historical_data = c(2,3,4),
  time = c(1,2,3)
) %>% 
  as_tibble() %>% 
  gather(key = key, value = val, projection1:historical_data) %>%
  group_by(time) %>%
  mutate(pct_diff = (val  / val[key == "historical_data"]))

# Groups:   time [3]
   time key               val pct_diff
  <dbl> <chr>           <dbl>    <dbl>
1     1 projection1         2    1    
2     2 projection1         4    1.33 
3     3 projection1         3    0.75 
4     1 projection2         3    1.5  
5     2 projection2         1    0.333
6     3 projection2         4    1    
7     1 historical_data     2    1    
8     2 historical_data     3    1    
9     3 historical_data     4    1 

Если вы настаиваете на том, что столбец key является фактором, чем вам нужно было бы слегка изменить приведенный выше код.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...