【问题标题】:Create a conditional timeline based on events in R根据 R 中的事件创建条件时间线
【发布时间】:2018-05-01 21:00:56
【问题描述】:

我有数据,其中“法律”变量表示不同地方(“地点”)的立法变化:

Person  Place  Year  Law
1         A    1990   0
2         A    1991   1
3         A    1992   1
4         B    1990   0
5         B    1991   0
6         B    1992   1
7         B    1993   1
8         B    1993   1
9         B    1993   1
10        B    1992   1

基本上,该法律于 1991 年在 A 地实施,并在随后的所有时间段内一直有效。它于 1992 年在 B 地实施并一直有效,依此类推。

我想创建一个新变量,该变量在法律实施的那一年取值为 0,1 表示之后 1 年,2 表示之后 2 年,-1 表示前一年,-2 表示 2 年之前,等等。

我需要最终的数据框看起来像:

Person  Place  Year  Law  timeline 
1         A    1990   0     -1
2         A    1991   1      0
3         A    1992   1      1
4         B    1990   0     -2
5         B    1991   0     -1
6         B    1992   1      0
7         B    1993   1      1
8         B    1993   1      2
9         B    1993   1      2
10        B    1992   1      1

我试过了:

library(dplyr)
df %>% 
 group_by(Place) %>%
 arrange(Year) %>%
 mutate(timeline = rank(Law))

但它不像我需要的那样工作。我究竟做错了什么?我可以在 dplyr 中执行此操作还是需要创建一个复杂的 for 循环?

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    您可以通过实现Law 的索引减去row_numer

    df %>% 
        arrange(Year) %>% 
        group_by(Place) %>% 
        mutate(timeline = row_number() - which(diff(Law) == 1) - 1) %>% 
        arrange(Place)
    
    # A tibble: 7 x 5
    # Groups:   Place [2]
    #  Person Place  Year   Law timeline
    #   <int> <fct> <int> <int>    <dbl>
    #1      1 A      1990     0      -1.
    #2      2 A      1991     1       0.
    #3      3 A      1992     1       1.
    #4      4 B      1990     0      -2.
    #5      5 B      1991     0      -1.
    #6      6 B      1992     1       0.
    #7      7 B      1993     1       1.
    

    【讨论】:

    • 或许row_number() - which.max(Law == 1)
    • @Henrik 更好!
    • 这不仅仅是代码高尔夫,它是闪电般的代码高尔夫。我似乎回想起几年(几十年)前的 ACM 编程竞赛,那里有更复杂的问题,但最后一秒提交/改进类似。
    • 不幸的是,我每年在每个地方都有很多观察结果,这意味着 row_number() 函数被无可救药地抛弃了。我想我的代码示例应该更清楚......
    • 在您的示例中,每个地点/年份组合只有一行。也许您可以使用反映您的实际数据的不同示例进行更新?
    【解决方案2】:

    使用data.table

    library(data.table)
    setDT(dat)[,timeline:=sequence(.N)-which.min(!Law),by=Place]
    dat
       Person Place Year Law timeline
    1:      1     A 1990   0       -1
    2:      2     A 1991   1        0
    3:      3     A 1992   1        1
    4:      4     B 1990   0       -2
    5:      5     B 1991   0       -1
    6:      6     B 1992   1        0
    7:      7     B 1993   1        1
    

    使用基础 r:

    transform(dat,timeline=ave(Law,Place,FUN=function(x)1:length(x)-which.min(!x)))
      Person Place Year Law timeline
    1      1     A 1990   0       -1
    2      2     A 1991   1        0
    3      3     A 1992   1        1
    4      4     B 1990   0       -2
    5      5     B 1991   0       -1
    6      6     B 1992   1        0
    7      7     B 1993   1        1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-09
      • 1970-01-01
      • 2021-03-18
      • 2015-05-11
      • 1970-01-01
      • 2022-11-13
      • 2019-11-06
      • 1970-01-01
      相关资源
      最近更新 更多