2017-04-18 9 views
1

Wie kategorisiere ich jede Zeile in einem großen R-Datenrahmen (> 2 Millionen Zeilen) basierend auf Datumsbereichsdefinitionen in einem separaten, viel kleineren R-Datenrahmen (12 Zeilen)?kategorisieren basierend auf Datumsbereichen in R

Mein großer Datenrahmen erfaßt, sieht ähnlich wie wenn über head(captures) genannt:

 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 

Mein kleinen Datenrahmen, Jahreszeiten, sieht ähnlich aus wie das in seiner Gesamtheit:

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 

Ich muß Fügen Sie meinem Captures-Datenrahmen eine "Saison" -Spalte hinzu, in der der Wert anhand von if und wo captures$date in den in den Jahreszeiten definierten Bereichen ermittelt wird.

Hier ist eine lang-hand-Lösung, die ich für mich nicht funktioniert, weil mein Datenrahmen so groß ist.

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

Auch dies funktioniert nicht für mich, da R jedes Mal abstürzt. Ich erkenne auch, dass dies die Vektorisierung in R nicht nutzt. Jede Hilfe hier wird geschätzt!

Antwort

0

Es wäre in der Tat groß, wenn Sie effizient einen join Betrieb tun könnten basierend auf einen Bereich von Werten statt Gleichheit. Leider weiß ich nicht, ob eine allgemeine Lösung existiert. In der Zwischenzeit empfehle ich eine einzige for-Schleife zu verwenden.

Die Effizienz der Vektorisierung wird am besten mit den höchsten Daten erreicht. Das heißt, wenn wir einen Datenrahmen schleifen und den anderen vektorisieren, ist es sinnvoller, den längeren Vektor zu vektorisieren und auf den kürzeren zu schleifen. In diesem Sinne werden wir den Rahmen der Jahreszeiten wiederholen und die 2M Datenreihen vektorisieren.

dat$season <- NA 

Schleife um jede der Jahreszeiten Reihen:

Ihre Daten: nicht definiert

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) 

Und der den Vorgang starten, gehen wir davon aus, dass alle season Daten noch ist

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

Hier ist nicht equi joi ns aus data.table:

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] 

Für jede Zeile in captures, entspricht der Index auf die ersten Reihe (mult="first") in seasons wird herausgefunden auf der Grundlage der Bedingung on Argument vorgesehen entsprechen. Der Wert von Season für entsprechende Indizes wird dann zurückgegeben und unter ans gespeichert. Es wird dann als eine neue Spalte zu seasons durch Bezugnahme hinzugefügt.

Ich habe es in zwei Schritten aus Gründen des Verständnisses gezeigt.


Sie können die erste passende Indizes sehen von which=TRUE statt mit:

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

Sie mit sqldf versuchen könnten. Beachten Sie, dass ich den Punkt in Opening_Date und Closing_Date in ein "_" ändern musste.

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 

Daten

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

oder vielleicht 'c.date zwischen s.Opening_Date und s.Closing_Date' als die' where' Klausel. Außerdem müssen Sie die Variablennamen nicht ändern, wenn Sie sie ausschließen, indem Sie sie in doppelte Anführungszeichen setzen oder sie mit [...] umgeben. –

Verwandte Themen