繁体   English   中英

r data.table 仅在每组至少有一个递增 obs 时调整最小和最大年数

[英]r data.table adjust min and max years only if each set has at least one incrementing obs

我有一个包含 id、位置、开始年份、结束年份、年龄 1 和年龄 2 的数据集。 对于定义为 id、location、age1 和 age2 的每个组,我想创建新的开始和结束年份。 例如,我可能有 3 个 china 条目,包括 0-4 岁。一个是 2000-2000,另一个是 2001-2001,最后一个是 2005-2005。 由于前两个条目中的年份以 1 递增,因此我希望它们相应的 newstart 和 newend 为 2000-2001。 第三个条目将具有 newstart==2005 和 newend==2005,因为这不是连续年份的一部分。

我拥有的数据表类似于以下内容,除了它有数千个条目许多组合:

    id    location   start   end   age1   age2
    1     brazil     2000    2000  0      4
    1     brazil     2001    2001  0      4
    1     brazil     2002    2002  0      4
    2     argentina  1990    1991  1      1
    2     argentina  1991    1991  2      2
    2     argentina  1992    1992  2      2
    2     argentina  1993    1993  2      2
    3     belize     2001    2001  0.5    1
    3     belize     2005    2005  1      2

我想更改数据表,使其如下所示

    id    location   start   end   age1   age2  newstart   newend
    1     brazil     2000    2000  0      4     2000       2002
    1     brazil     2001    2001  0      4     2000       2002
    1     brazil     2002    2002  0      4     2000       2002
    2     argentina  1990    1991  1      1     1991       1991
    2     argentina  1991    1991  2      2     1991       1993
    2     argentina  1992    1992  2      2     1991       1993
    2     argentina  1993    1993  2      2     1991       1993
    3     belize     2001    2001  0.5    1     2001       2001
    3     belize     2005    2005  1      2     2005       2005

我尝试创建一个变量,使用滞后来跟踪前一年和当年的差异,然后计算这两年之间的差异。 然后我通过放置最小起点和最大终点来创建新起点和新终点。 我发现这仅在连续年份有一组 2 时才有效。 如果我有一个更大的集合,这不起作用,因为它无法跟踪每个分组的年份增加 1 的 obs 数量。 我相信我需要某种类型的循环。

有没有更有效的方法来实现这一目标?

我们可以使用dplyr 按'id'分组后,取'start'和'start'的lag之差,应用rleid得到run-length-id'并创建'newstart','newend'作为minmax的“开始”

library(dplyr)
library(data.table)
df1 %>% 
   group_by(id) %>%
   group_by(grp =  rleid(replace_na(start - lag(start), 1)),
     .add = TRUE) %>%
   mutate(newstart = min(start), newend = max(end))

-输出

# A tibble: 9 x 9
# Groups:   id, grp [4]
#     id location  start   end  age1  age2   grp newstart newend
#  <int> <chr>     <int> <int> <dbl> <int> <int>    <int>  <int>
#1     1 brazil     2000  2000   0       4     1     2000   2002
#2     1 brazil     2001  2001   0       4     1     2000   2002
#3     1 brazil     2002  2002   0       4     1     2000   2002
#4     2 argentina  1990  1991   1       1     1     1990   1993
#5     2 argentina  1991  1991   2       2     1     1990   1993
#6     2 argentina  1992  1992   2       2     1     1990   1993
#7     2 argentina  1993  1993   2       2     1     1990   1993
#8     3 belize     2001  2001   0.5     1     1     2001   2001
#9     3 belize     2005  2005   1       2     2     2005   2005

或者使用data.table

library(data.table)
setDT(df1)[, grp := rleid(replace_na(start - shift(start), 1))
         ][, c('newstart', 'newend') := .(min(start), max(end)), .(id, grp)][, grp := NULL]

数据表

你用标记,所以我的第一个建议是:

library(data.table)
dat[, contiguous := rleid(c(TRUE, diff(start) == 1)), by = .(id)]
dat[, c("newstart", "newend") := .(min(start), max(end)), by = .(id, contiguous)]
dat[, contiguous := NULL]
dat
#    id  location start  end age1 age2 newstart newend
# 1:  1    brazil  2000 2000  0.0    4     2000   2002
# 2:  1    brazil  2001 2001  0.0    4     2000   2002
# 3:  1    brazil  2002 2002  0.0    4     2000   2002
# 4:  2 argentina  1990 1991  1.0    1     1990   1993
# 5:  2 argentina  1991 1991  2.0    2     1990   1993
# 6:  2 argentina  1992 1992  2.0    2     1990   1993
# 7:  2 argentina  1993 1993  2.0    2     1990   1993
# 8:  3    belize  2001 2001  0.5    1     2001   2001
# 9:  3    belize  2005 2005  1.0    2     2005   2005

基数R

相反,如果你真的只是指data.frame ,那么

dat <- transform(dat, contiguous = ave(start, id, FUN = function(a) cumsum(c(TRUE, diff(a) != 1))))
dat <- transform(dat,
  newstart = ave(start, id, contiguous, FUN = min),
  newend   = ave(end  , id, contiguous, FUN = max)
)
# Warning in FUN(X[[i]], ...) :
#   no non-missing arguments to min; returning Inf
# Warning in FUN(X[[i]], ...) :
#   no non-missing arguments to min; returning Inf
# Warning in FUN(X[[i]], ...) :
#   no non-missing arguments to max; returning -Inf
# Warning in FUN(X[[i]], ...) :
#   no non-missing arguments to max; returning -Inf

dat
#   id  location start  end age1 age2 newstart newend contiguous
# 1  1    brazil  2000 2000  0.0    4     2000   2002          1
# 2  1    brazil  2001 2001  0.0    4     2000   2002          1
# 3  1    brazil  2002 2002  0.0    4     2000   2002          1
# 4  2 argentina  1990 1991  1.0    1     1990   1993          1
# 5  2 argentina  1991 1991  2.0    2     1990   1993          1
# 6  2 argentina  1992 1992  2.0    2     1990   1993          1
# 7  2 argentina  1993 1993  2.0    2     1990   1993          1
# 8  3    belize  2001 2001  0.5    1     2001   2001          1
# 9  3    belize  2005 2005  1.0    2     2005   2005          2
dat$contiguous <- NULL

我刚刚了解到ave有趣的一点:它使用interaction(...) (所有分组变量),它将给出所有可能的组合,而不仅仅是在数据中观察到的组合。 因此,可以使用零数据调用FUN 在这种情况下,它确实发出了警告。 人们可以用抑制这种function(a) suppressWarnings(min(a))而不仅仅是min

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM