【问题标题】:How can I generate lags of data nested in multiple columns?如何生成嵌套在多列中的数据滞后?
【发布时间】:2021-06-12 20:28:03
【问题描述】:

我的目标是计算嵌套在空间单位中的年龄组随时间的增长率。我正在使用的数据框的结构是这样的(但要大得多):

set.seed(1234)

df <- data.frame(Time = c(1,1,1,1,2,2,2,2,3,3,3,3),
                 Region = rep(c("A", "A", "B", "B"),3),
                 Age = rep(c(1,2), 6),
                 No_Persons = round(rnorm(12, mean = 10),0))

Region 的每个类别中,我需要将No_Persons 从一年到另一年(Time)以及Age 组1 和2 之间的变化。所以基本上操作将是Age2_Time2 /Age1_Time1。我尝试使用各种lag-functions 以及data.table::shift 来实现我的目标,但无法让它发挥作用。例如,我虽然这会给我想要的结果,但它只会吐出NAs

library(tidyverse)

df %>% 
  group_by(Region) %>%
  mutate(Ratio = No_Persons / dplyr::lag(No_Persons,
                                      n = 1,
                                      order_by = "Age"))

我通过使用pivot_wider 得到正确的结果,然后通过使用列手动计算增长率,如下所示:

df %>% 
  pivot_wider(names_from = "Age", values_from = "No_Persons") %>%
  group_by(Region) %>%
  mutate(Ratio = `2` / dplyr::lag(`1`, order_by = Time))

# A tibble: 6 x 5
# Groups:   Region [2]
   Time Region   `1`   `2`  Quote
  <dbl> <chr>  <dbl> <dbl>  <dbl>
1     1 A          9    10 NA    
2     1 B         11     8 NA    
3     2 A         10    11  1.22 
4     2 B          9     9  0.818
5     3 A          9     9  0.9  
6     3 B         10     9  1    

但是,由于原始数据集有更多的年龄组,这变得乏味且容易出错。我更喜欢程序化解决方案。

【问题讨论】:

    标签: r data.table tidyverse


    【解决方案1】:

    更新答案

    根据您的评论,我重构了最小数据集df,包含 3 个时间点、2 个区域和 3 个年龄组。

    set.seed(1234)
    time.number = 3
    region.number = 2
    age.number = 3
    total.number = time.number * region.number * age.number
    df <-
      data.frame(
        Time = rep(1:time.number, each = region.number * age.number),
        Region = rep(LETTERS[1:region.number], each = age.number),
        Age = rep(seq(1, age.number), region.number),
        No_Persons = round(rnorm(total.number, mean = 10), 0)
      )
    df
    

    以下解决方案也应适用于您的真实数据。

    library(data.table)
    library(magrittr)
    # set df as data.table
    setDT(df)
    
    # calculate the number from real data
    age.number <- df[,Age] %>% unique() %>% length()
    region.number <- df[,Region] %>% unique() %>% length()
    
    df[,.(V1=.SD[1:age.number-1,No_Persons],
          V2=.SD[2:age.number,No_Persons]),
       by = .(Time,Region)][,Radio:=V2/lag(V1,region.number)][]
    

    结果:

       Time Region V1 V2    Radio
     1:    1      A  9 10       NA
     2:    1      A 10 11       NA
     3:    1      B  8 10 1.111111
     4:    1      B 10 11 1.100000
     5:    2      A  9  9 1.125000
     6:    2      A  9  9 0.900000
     7:    2      B  9 10 1.111111
     8:    2      B 10  9 1.000000
     9:    3      A  9 10 1.111111
    10:    3      A 10 11 1.100000
    11:    3      B 10  9 1.000000
    12:    3      B  9  9 0.900000
    

    上一个答案

    我不确定这是否是你想要的结果,但它确实可以得到正确的结果。

    library(data.table)
    setDT(df)[,.(V1 = No_Persons[seq(1,.N,2)],
                 V2 = No_Persons[seq(2,.N,2)]
                ),
              by = .(Time,Region)][,Radio:=V2/lag(V1,2)]
    

    【讨论】:

    • 谢谢,这似乎可行。不过,我不太明白代码的作用,特别是这部分:V1 = No_Persons[seq(1,.N,2)], V2 = No_Persons[seq(2,.N,2)] 你会这么友善和详细吗?
    • 它提取df的奇偶行,对应于你的1和2。
    • 感谢您的澄清。数据是根据偶数/奇数构造的事实是我试图提供一个可概括的例子的产物。我的真实数据在No_Persons 的两个年龄组中都有随机数。我将编辑我的问题以反映这一点。
    • 您的解决方案仍然有效,所以我一定误解了解释。但它并不能推广到我的真实数据,因为我有更多的年龄组。
    • @tifu 我不清楚这么多年龄组意味着什么。你能提供至少两个年龄段的例子吗?
    猜你喜欢
    • 2018-02-03
    • 1970-01-01
    • 2020-04-10
    • 2021-04-21
    • 2018-11-27
    • 2011-03-09
    • 2019-02-14
    • 1970-01-01
    • 2020-06-06
    相关资源
    最近更新 更多