如何让tapply不受INDEX列顺序影响,按数据集自然顺序生成分组日期序变量?
分组生成日期序变量时保持原数据顺序
原始数据
Subject Site Date 1 2 '2020-01-01' 1 2 '2020-01-01' 1 2 '2020-01-02' 2 1 '2020-01-02' 2 1 '2020-01-03' 2 1 '2020-01-03'
期望结果
按Subject和Site分组,为唯一日期生成序变量,期望输出:
Want 1 1 2 1 2 2
遇到的问题
自定义生成序变量的函数:
rle <- function(x) cumsum(!duplicated(x))
使用tapply时,INDEX参数的列顺序不同会导致结果顺序与原数据不一致:
have1 <- unlist(tapply(val$Date, val[, c( 'Site', 'Subject')], rle)) have2 <- unlist(tapply(val$Date, val[, c('Subject', 'Site')], rle))
输出结果:
> have1 [1] 1 1 2 1 2 2 > have2 [1] 1 2 2 1 1 2
解决方案
方法1:使用ave函数
ave函数会自动保留原数据的顺序,无需担心分组变量的顺序:
val$Want <- ave(val$Date, val$Subject, val$Site, FUN = function(x) cumsum(!duplicated(x)))
方法2:使用dplyr包(tidyverse风格)
通过分组后突变的方式,严格保留原始数据行顺序:
library(dplyr) val <- val %>% group_by(Subject, Site) %>% mutate(Want = cumsum(!duplicated(Date))) %>% ungroup()
方法3:使用data.table包
适合大数据集处理,同样保留原数据顺序:
library(data.table) setDT(val)[, Want := cumsum(!duplicated(Date)), by = .(Subject, Site)]
以上三种方法中,分组变量的顺序均不会影响最终结果的行排列,完全遵循数据集的自然顺序。
内容的提问来源于stack exchange,提问作者AdamO
相关产品推荐
相关产品推荐

