2016-06-22 4 views
1

私は、縦方向のジオコーディングされたアドレスデータと各ジオコードでの時間長を持っています。次に、各ジオイド位置の特性を与える一連の変数(ここではそれらをxと呼んでいます)があります。ここには2つのケースがありますが、私には何千ものケースがあります。各アドレスに時間の長さによって重み付けされ、私は毎年(2004年、2005年、2006年、2007年)のために、それぞれのケースについて単一の値(1、7)で終わる必要がありdplyrで日付を操作する

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 

。ケース1は2004年にジオイド53から45に移動し、ケース7はジオイド16から2007年には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スライスで実行可能かもしれないようだが、私は現時点では失速している。キーは毎年分離しています。

答えて

2

うまくいけば、これはあなたを始めてくれるでしょう。 startからendまでの期間が1年以上または暦年を超えているケースをどのように処理したいかについてはわかりませんでした。言及eipi10として

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 
4

、あなたのデータの一部は、1年以上に及びます。時間差計算で使用したデータとは一貫していないように見えますが、それらはすべて同じ年内にあります。

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 
+0

これは実際に私が得ようとしている正確な質問です。私は年を重ねてデータを持っていますが、それぞれの年ごとに指標が必要です。それは私のデータから外挿する方法を見つけることができない部分です – swhusky

+0

id、geoid、xはそれぞれの年に分割して同じ値を扱いますか? –

-1

私は簡単な機能につながるいくつかのローカルヘルプを見つけることができました。私たちは依然として日付を使ってapplyを使う方法に固執していますが、全体的にこれを扱います。

#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) 

} 
+0

ループ内でオブジェクトを成長させることは、R. – Frank

+0

では、このインスタンスでは他にどのような戦略をお勧めしますか? – swhusky

+0

ループ内の 'rbind'がなぜ有用であると思うのかを知るためにあなたのコードを慎重に読んでいないので、私はそこから最良の方法を知りません。'prop'が0になるようにするので、あなたの関数はスカラー値であると思います。この場合、' mapply'があなたのために働くかもしれません。通常の参考資料は、本書の短い第2章です。http://www.burns-stat.com/pages/Tutor/R_inferno.pdfこれは役に立つかもしれません。 – Frank