【问题标题】:Divide by value for a specific factor given time (dplyr, data.table)给定时间除以特定因子的值(dplyr,data.table)
【发布时间】:2019-10-17 10:02:03
【问题描述】:

我有这样的长格式数据:

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 的值相对于history_data 的相对差异。因此,我希望我的数据最终是这样的:

# 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 解决方案?或者,也许您可​​以将我引导到已经回答的问题。我自己没遇到过。

谢谢

【问题讨论】:

    标签: r dataframe dplyr data.table


    【解决方案1】:

    这是一种可能的方法,使用 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")
    

    【讨论】:

    • grep("historical_data", key) 效率不会很高,为什么不是key=="historical_data"
    【解决方案2】:

    这是使用组的一种简单方法:

     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 列是一个因素,那么您将不得不稍微修改上面的代码。

    【讨论】:

    • 太好了,启发了我以下,我可以保留我的因素:df %&gt;% mutate(key = key %&gt;% factor() %&gt;% fct_relevel("historical_data")) %&gt;% arrange(key) %&gt;% group_by(time) %&gt;% mutate(pct_diff = (val / first(val, order_by = c(key))))
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-12
    • 1970-01-01
    • 1970-01-01
    • 2016-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多