使用dplyr操作日期

时间:2016-06-22 01:57:05

标签: r date dplyr

我有纵向地理编码的地址数据和每个地理编码的时间长度。然后我有一系列变量(我在这里称它们为x),它们给出了每个大地水准面位置的特征。下面只有两个案例,但我有数千个。

id<-c(1,1,1,7,7,7,7)
geoid<-c(53,45,45,16,18,42)
start<-c("1/1/2004","10/31/2004","1/1/2005","1/1/2005","6/1/2007","7/2/2007")
end<-c("10/30/2004","12/31/2004","12/31/2007","5/31/2007","7/1/2007","12/31/2007")
x<-c(.5,.7,.7,.3,.4,.6)
dat<-data.frame(id,geoid,x,start,end)
dat$start<-as.Date(dat$start,format='%m/%d/%Y')
dat$end<-as.Date(dat$end,format='%m/%d/%Y')
dat

  id geoid   x      start        end
   1    53 0.5 2004-01-01 2004-10-30
   1    45 0.7 2004-10-31 2004-12-31
   1    45 0.7 2005-01-01 2007-12-31
   7    16 0.3 2005-01-01 2007-05-31
   7    18 0.4 2007-06-01 2007-08-01
   7    42 0.6 2007-08-02 2007-12-31

我需要每年(2004年,2005年,2006年,2007年)以及每个案例(1,7)以单个值结束,并根据每个地址的时间长度进行加权。所以案例1在2004年从大地水准面53移动到45,案例7在2007年从大地水准面16移动到18到42.所以我计算每个大地水准面的年份百分比(最终我将乘以x乘以平均值每年得到一个加权平均值)。停留一整年的病例将获得1的重量。

#calculate the percentage of year at each address for id 1
(as.Date("10/31/2004",format='%m/%d/%Y')-as.Date("1/1/2004",format='%m/%d/%Y'))/365.25
Time difference of 0.8323066
(as.Date("12/31/2004",format='%m/%d/%Y')-as.Date("10/31/2004",format='%m/%d/%Y'))/365.25
Time difference of 0.1670089

#calculate the percentage of year at each address for id 7
(as.Date("05/31/2007",format='%m/%d/%Y')-as.Date("1/1/2007",format='%m/%d/%Y'))/365.25
Time difference of 0.4106776
(as.Date("07/01/2007",format='%m/%d/%Y')-as.Date("06/01/2007",format='%m/%d/%Y'))/365.25
Time difference of 0.08213552
(as.Date("12/31/2007",format='%m/%d/%Y')-as.Date("07/02/2007",format='%m/%d/%Y'))/365.25
Time difference of 0.4982888

我可以通过单独查看每年的暴力来计算,计算在该地址所花费的年份的百分比。然后我将每个权重乘以x值并取当年的平均值 - 这对数千个案例来说是不可能的。如何更有效地解决这个问题的任何想法将非常感激。看起来dplyr切片可能是可行的但是我现在已经停滞不前了。关键是每年分离出来。

3 个答案:

答案 0 :(得分:4)

正如eipi10所提到的,你的一些数据跨越了一年多。它看起来与您在时差计算中使用的数据不一致,这些数据都在同一年内。

假设您的开始和结束日期实际上是在同一年,您可以执行以下操作:

foo <- dat %>%
         mutate(start_year=year(dat$start), 
                end_year=year(dat$end), 
                same_year=(start_year==end_year), 
                year_frac=as.numeric(dat$end - dat$start)/365.25,
                wtd_x = year_frac * x)

这会给你:

id geoid   x      start        end start_year end_year same_year  year_frac      wtd_x
1  1    53 0.5 2004-01-01 2004-10-31       2004     2004      TRUE 0.83230664 0.41615332
2  1    45 0.7 2004-10-31 2004-12-31       2004     2004      TRUE 0.16700890 0.11690623
3  1    45 0.7 2005-01-01 2007-12-31       2005     2007     FALSE 2.99520876 2.09664613
4  7    16 0.3 2007-01-01 2007-05-31       2007     2007      TRUE 0.41067762 0.12320329
5  7    18 0.4 2007-06-01 2007-07-01       2007     2007      TRUE 0.08213552 0.03285421
6  7    42 0.6 2007-07-02 2007-12-31       2007     2007      TRUE 0.49828884 0.29897331

然后,您可以使用以下方式对数据进行分组和汇总:

bar <- foo %>%
  group_by(start_year, id) %>%
 summarise(sum(wtd_x))

给你答案:

start_year    id     sum(wtd_x)
   (dbl) (dbl)         (dfft)
1       2004     1 0.5330595 days
2       2005     1 2.0966461 days
3       2007     7 0.4550308 days

答案 1 :(得分:2)

希望这会让你开始。我不确定您是如何处理从startend的时间跨度超过一年或超过历年的情况。

library(dplyr)

dat %>% 
  mutate(fractionOfYear = as.numeric(end - start)/365.25)
  id geoid   x      start        end fractionOfYear
1  1    53 0.5 2004-01-01 2004-10-30     0.82956879
2  1    45 0.7 2004-10-31 2004-12-31     0.16700890
3  1    45 0.7 2005-01-01 2007-12-31     2.99520876
4  7    16 0.3 2005-01-01 2007-05-31     2.40930869
5  7    18 0.4 2007-06-01 2007-07-01     0.08213552
6  7    42 0.6 2007-07-02 2007-12-31     0.49828884

答案 2 :(得分:-1)

我能够找到一些帮助我们完成简单功能的本地帮助。我们仍然坚持如何使用申请日期,但这总体上处理它。

#made up sample address data
id<-c(1,1,1,7,7,7)
geoid<-c(53,45,45,16,18,42)
start<-c("1/31/2004","10/31/2004","1/1/2005","1/1/2005","6/1/2007","7/2/2007")
end<-c("10/30/2004","12/31/2004","12/31/2007","5/31/2007","7/1/2007","12/31/2007")

dat <- data.frame(id,geoid,start,end)

#format addresses
dat$start<-as.Date(dat$start,format='%m/%d/%Y')
dat$end<-as.Date(dat$end,format='%m/%d/%Y')

#function to create proportion of time at each address
prop_time <- function(drange, year){

  start <- drange[[1]]; end <- drange[[2]]

  #start year and end year
  syear <- as.numeric(format(start,'%Y'))
  eyear <- as.numeric(format(end,'%Y'))

  #select only those dates that are within the same year
  if(syear<=year & year<=eyear){

    byear <- as.Date(paste("1/1", sep="/", year), format='%m/%d/%Y')
    eyear <- as.Date(paste("12/31", sep="/", year), format='%m/%d/%Y')

    astart <- max(byear, start)
    aend <- min(eyear, end)

    prop <- as.numeric((aend - astart))/as.numeric((eyear - byear))

  } else prop <- 0 #if no proportion within same year calculated then gets 0

  prop

}

#a second function to apply prop_time to multiple cases
prop_apply <- function(dat_times, year){

  out <- NULL

  for(i in 1:dim(dat_times)[1]){
    out <- rbind(out,prop_time(dat_times[i,], year))
  }

  out

}


#create new data frame to populate years
dat <- data.frame(dat, y2004=0, y2005=0, y2006=0, y2007=0)
dat_times <- dat[,c("start", "end")]

#run prop_apply in a loop across cases and selected years
for(j in 2004:2007){

  newdate <- paste("y", j, sep="")
  dat[,newdate] <- prop_apply(dat_times, j)

}