2017-04-18 64 views
1

如何根據日期範圍定義將大R數據框(> 200萬行)中的每行分類爲單獨的,更小的R數據框(12行)?當通過head(captures)稱爲根據R中的日期範圍進行分類

我的大數據幀,捕獲,類似於此:

 id  date sex 
1 160520 2016-11-22 1 
2 1029735 2016-11-12 1 
3 1885200 2016-11-05 1 
4 2058366 2015-09-26 2 
5 2058367 2015-09-26 1 
6 2058368 2015-09-26 1 

我的小數據幀,季節,查看其全部與此類似:

Season Opening.Date Closing.Date 
    2016 2016-09-24 2017-01-15 
    2015 2015-09-26 2016-01-10 
    2014 2014-09-27 2015-01-11 
    2013 2013-09-28 2014-01-12 
    2012 2012-09-22 2013-01-13 
    2011 2011-09-24 2012-01-08 
    2010 2010-09-25 2011-01-16 
    2009 2009-09-26 2010-01-17 
    2008 2008-09-27 2009-01-18 
    2007 2007-09-22 2008-01-13 
    2006 2006-09-23 2007-01-14 
    2005 2005-09-24 2006-01-15 

我需要將「季節」列添加到我的捕獲數據框中,其中值將根據是否在captures$date處於季節定義的範圍內確定。

這是我提出的一個長期解決方案,因爲我的數據框非常大,所以對我來說並不合適。

#add packages 
library(dplyr) 
library(lubridate) 
#make blank column 
captures$season=NA 
for (i in 1:length(seasons$Season)){ 
    for (j in 1:length(captures$id{ 
    captures$season[j]=ifelse(between(captures$date[j],ymd(seasons$Opening.Date[i]),ymd(seasons$Closing.Date[i])),seasons$Season[i],captures$season[j]) 
    } 
} 

再次,這不適合我,因爲R每次崩潰。我也意識到這不利用R中的矢量化。在這裏的任何幫助表示讚賞!

回答

0

這將是巨大的確,如果你能有效地基於價值而不是平等範圍join操作。不幸的是,我不知道是否存在一個通用的解決方案。目前,我建議使用一個for循環。

矢量化的效率最好沿着最高的數據完成。也就是說,如果我們循環一個data.frame並向另一個data.frame進行矢量化,則將較長的向量和較短的向量進行向量化會更有意義。考慮到這一點,我們將循環使用季節框架並向量化2M行數據。

您的數據:

txt <- "Season Opening.Date Closing.Date 
    2016 2016-09-24 2017-01-15 
    2015 2015-09-26 2016-01-10 
    2014 2014-09-27 2015-01-11 
    2013 2013-09-28 2014-01-12 
    2012 2012-09-22 2013-01-13 
    2011 2011-09-24 2012-01-08 
    2010 2010-09-25 2011-01-16 
    2009 2009-09-26 2010-01-17 
    2008 2008-09-27 2009-01-18 
    2007 2007-09-22 2008-01-13 
    2006 2006-09-23 2007-01-14 
    2005 2005-09-24 2006-01-15" 
seasons <- read.table(text = txt, header = TRUE) 
seasons[2:3] <- lapply(seasons[2:3], as.Date) 

txt <- "  id  date sex 
1 160520 2016-11-22 1 
2 1029735 2016-11-12 1 
3 1885200 2016-11-05 1 
4 2058366 2015-09-26 2 
5 2058367 2015-09-26 1 
6 2058368 2015-09-26 1" 
dat <- read.table(text = txt, header = TRUE) 
dat$date <- as.Date(dat$date) 

和啓動過程中,我們假設所有數據的season是尚未定義的:

dat$season <- NA 

環圍繞每個季節行:

for (i in seq_len(nrow(seasons))) { 
    dat$season <- ifelse(is.na(dat$season) & 
         dat$date >= seasons$Opening.Date[i] & 
         dat$date < seasons$Closing.Date[i], 
         seasons$Season[i], dat$season)      
} 
dat 
#  id  date sex season 
# 1 160520 2016-11-22 1 2016 
# 2 1029735 2016-11-12 1 2016 
# 3 1885200 2016-11-05 1 2016 
# 4 2058366 2015-09-26 2 2015 
# 5 2058367 2015-09-26 1 2015 
# 6 2058368 2015-09-26 1 2015 
1

這裏使用的是non equi joi從data.table NS:

require(data.table) # v1.10.4+ 
setDT(captures) # convert data.frames to data.tables 
setDT(seasons) 

ans <- seasons[captures, Season, 
       on=.(Opening.Date<=date, Closing.Date>=date), 
       mult="first"] 
# [1] 2016 2016 2016 2015 2015 2015 
seasons[, season := ans] 

對於每一行中captures,對應於索引首先在seasons匹配行(mult="first")基於提供給on參數中的條件被計算出來。相應指數的Season的值然後返回並保存在ans下。然後通過引用將其作爲新列添加到seasons

爲了理解,我已經在兩個步驟中展示了它。


您可以通過使用which=TRUE而不是看到的第一個匹配指數:

seasons[captures, 
      on=.(Opening.Date<=date, Closing.Date>=date), 
      mult="first", 
      which=TRUE] 
# [1] 1 1 1 2 2 2 
0

您可以用sqldf嘗試。請注意,我必須將Opening_Date和Closing_Date中的點改爲「_」。

library(sqldf) 

captures$season <- sqldf("select Season from seasons s, captures c 
where c.date >= s.Opening_Date and c.date <= s.Closing_Date") 
captures  
     id  date sex Season 
1 160520 2016-11-22 1 2016 
2 1029735 2016-11-12 1 2016 
3 1885200 2016-11-05 1 2016 
4 2058366 2015-09-26 2 2015 
5 2058367 2015-09-26 1 2015 
6 2058368 2015-09-26 1 2015 

數據

txt <- "Season Opening_Date Closing_Date 
    2016 2016-09-24 2017-01-15 
    2015 2015-09-26 2016-01-10 
    2014 2014-09-27 2015-01-11 
    2013 2013-09-28 2014-01-12 
    2012 2012-09-22 2013-01-13 
    2011 2011-09-24 2012-01-08 
    2010 2010-09-25 2011-01-16 
    2009 2009-09-26 2010-01-17 
    2008 2008-09-27 2009-01-18 
    2007 2007-09-22 2008-01-13 
    2006 2006-09-23 2007-01-14 
    2005 2005-09-24 2006-01-15" 
seasons <- read.table(text = txt, header = TRUE) 
seasons[2:3] <- lapply(seasons[2:3], as.Date) 

txt <- "  id  date sex 
1 160520 2016-11-22 1 
2 1029735 2016-11-12 1 
3 1885200 2016-11-05 1 
4 2058366 2015-09-26 2 
5 2058367 2015-09-26 1 
6 2058368 2015-09-26 1" 
captures <- read.table(text = txt, header = TRUE) 
captures$date <- as.Date(captures$date) 
+0

或也許's.Opening_Date和s.Closing_Date'之間c.date作爲'where'子句。另外,如果您通過將它們放在雙引號中或用[...]包圍它們來避開它們,則不必更改變量名稱。 –