2017-04-18 23 views
1

大規模なRデータフレーム(12行)の日付範囲定義に基づいて、大規模なRデータフレーム(200万行以上)の各行を分類するにはどうすればよいですか?日付範囲に基づいて分類する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 

私の小さなデータフレーム、季節を、その全体がこのようになります:

私の大きなデータフレーム、キャプチャは、head(captures)経由で呼び出されたときに、このようになります

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 

私がする必要があります私のキャプチャのデータフレームに 'season'カラムを追加します。値は、captures$dateがwhenとwhereに基づいて決定され、季節で定義された範囲に含まれます。

私が思いついた長年の解決策は、自分のデータフレームが非常に大きいので、私にとってはうまくいきません。

#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ループを使用することをお勧めします。

ベクトル化の効率は、最も高いデータに沿って最もよく行われます。つまり、1つのdata.frameにループし、もう一方をベクトル化すると、長い方のベクトルをベクトル化し、短い方のベクトルでループする方が理にかなっています。これを念頭に置いて、季節のフレームをループし、2M行のデータをベクトル化します。

あなたのデータ:

dat$season <- NA 

ループを季節行の各周り:

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は、まだ定義されていないことを前提とし

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:capturesの各行について

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] 

は、最初seasonsに行(mult="first")と一致に対応するインデックスはon引数に提供条件に基づいて把握されます。対応するインデックスのSeasonの値が返され、ansの下に保存されます。これを参考にしてseasonsに新しい列として追加します。

私は、理解のために2つの手順で示しました。


代わり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のポイントを "_"に変更する必要がありました。 `WHERE`句として

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。また、変数名を二重引用符で囲むか、[...]で囲むことで変数名を変更する必要はありません。 –

関連する問題