Die effiziente und genaue Alter Berechnung (in Jahren, Monaten oder Wochen) in R gegeben, Geburtsdatum und einem beliebigen Datum

Ich bin mit der gemeinsamen Aufgabe, die Berechnung des Alters (in Jahren, Monaten oder Wochen) gegeben, das Geburtsdatum und ein willkürliches Datum. Die Sache ist die, dass sehr oft habe ich zu tun das über viele viele Datensätze (>300 Millionen), also performance ist ein zentrales Thema hier.

Nachdem eine schnelle Suche in SO und Google fand ich 3 alternativen:

  • Eine gemeinsame arithmetische Verfahren (/365.25) (link)
  • Verwendung von Funktionen new_interval() und duration() aus Paket lubridate (link)
  • Funktion age_calc() aus Paket eeptools (link, link, link)

So, hier ist mein Spielzeug-code:

# Some toy birthdates
birthdate <- as.Date(c("1978-12-30", "1978-12-31", "1979-01-01", 
                       "1962-12-30", "1962-12-31", "1963-01-01", 
                       "2000-06-16", "2000-06-17", "2000-06-18", 
                       "2007-03-18", "2007-03-19", "2007-03-20", 
                       "1968-02-29", "1968-02-29", "1968-02-29"))

# Given dates to calculate the age
givendate <- as.Date(c("2015-12-31", "2015-12-31", "2015-12-31", 
                       "2015-12-31", "2015-12-31", "2015-12-31", 
                       "2050-06-17", "2050-06-17", "2050-06-17",
                       "2008-03-19", "2008-03-19", "2008-03-19", 
                       "2015-02-28", "2015-03-01", "2015-03-02"))

# Using a common arithmetic procedure ("Time differences in days"/365.25)
(givendate-birthdate)/365.25

# Use the package lubridate
require(lubridate)
new_interval(start = birthdate, end = givendate) / 
                     duration(num = 1, units = "years")

# Use the package eeptools
library(eeptools)
age_calc(dob = birthdate, enddate = givendate, units = "years")

Reden wir später über die Genauigkeit und den Fokus zuerst auf die Leistung. Hier ist der code:

# Now let's compare the performance of the alternatives using microbenchmark
library(microbenchmark)
mbm <- microbenchmark(
    arithmetic = (givendate - birthdate) / 365.25,
    lubridate = new_interval(start = birthdate, end = givendate) /
                                     duration(num = 1, units = "years"),
    eeptools = age_calc(dob = birthdate, enddate = givendate, 
                        units = "years"),
    times = 1000
)

# And examine the results
mbm
autoplot(mbm)

Hier die Ergebnisse:

Die effiziente und genaue Alter Berechnung (in Jahren, Monaten oder Wochen) in R gegeben, Geburtsdatum und einem beliebigen Datum
Die effiziente und genaue Alter Berechnung (in Jahren, Monaten oder Wochen) in R gegeben, Geburtsdatum und einem beliebigen Datum

Fazit: die Leistung der lubridate und eeptools Funktionen ist viel schlimmer als das arithmetische Methode (/365.25 ist mindestens 10 mal schneller). Leider ist die arithmetische Methode ist nicht genau genug, und ich kann nicht leisten, die paar Fehler, die diese Methode machen.

"weil der Weg zu den modernen Gregorianischen Kalender
ist konstruiert, es ist keine einfache arithmetische
Methode, erzeugt ein person Alter, angegeben nach
gemeinsame Nutzung gemeinsame Nutzung bedeutet, dass eine person, die
Alter sollte immer eine ganze Zahl sein, die sich erhöht, genau auf
ein Geburtstag". (link)

Als ich Las einige Beiträge, die lubridate und eeptools machen keine solchen Fehler (obwohl ich noch nicht angeschaut, der code/Lesen Sie mehr über die Funktionen wissen, welche Methode Sie verwenden) und das ist, warum ich wollte, Sie zu benutzen, aber Ihre Leistung nicht für meine eigentlichen Anwendung.

Irgendwelche Ideen auf eine effiziente und genaue Methode zur Berechnung des Alters?

BEARBEITEN

Ops, es scheint lubridate auch Fehler macht. Und offenbar basiert auf diesem Beispiel Spielzeug, es macht mehr Fehler als der arithmetische Methode (siehe Zeilen 3, 6, 9, 12). (mache ich etwas falsch?)

toy_df <- data.frame(
    birthdate = birthdate,
    givendate = givendate,
    arithmetic = as.numeric((givendate - birthdate) / 365.25),
    lubridate = new_interval(start = birthdate, end = givendate) /
        duration(num = 1, units = "years"),
    eeptools = age_calc(dob = birthdate, enddate = givendate,
                        units = "years")
)
toy_df[, 3:5] <- floor(toy_df[, 3:5])
toy_df

    birthdate  givendate arithmetic lubridate eeptools
1  1978-12-30 2015-12-31         37        37       37
2  1978-12-31 2015-12-31         36        37       37
3  1979-01-01 2015-12-31         36        37       36
4  1962-12-30 2015-12-31         53        53       53
5  1962-12-31 2015-12-31         52        53       53
6  1963-01-01 2015-12-31         52        53       52
7  2000-06-16 2050-06-17         50        50       50
8  2000-06-17 2050-06-17         49        50       50
9  2000-06-18 2050-06-17         49        50       49
10 2007-03-18 2008-03-19          1         1        1
11 2007-03-19 2008-03-19          1         1        1
12 2007-03-20 2008-03-19          0         1        0
13 1968-02-29 2015-02-28         46        47       46
14 1968-02-29 2015-03-01         47        47       47
15 1968-02-29 2015-03-02         47        47       47
Ich würde sein überrascht, wenn es etwas gibt, was schneller/einfacher als lubridate. Mein einziger Vorschlag, wenn Sie realllly müssen die Leistungssteigerung ist die arithmetische Methode zuerst, und dann wiederholen alle den "close calls" mit den lubridate Methode (so, zum Beispiel, wenn abs(floor(age) - age) < 0.01) dann verwenden lubridate)
Danke. sind Sie und erfahrene Benutzer von lubridate?, ..., als ich es in der Frage bearbeitet, ich fand, dass es Fehler macht (vielleicht mehr als die arithmetische Methode) aber ich habe gelesen in mehreren posts, dass lubridate war in der Tat eine der R-Pakete, die in der Lage war, genau zu berechnen Altersgruppen. So, jetzt Frage ich mich, wenn ich mache etwas falsch. (Ich denke nicht, ich bin im Grunde nach den Beispielen und es ist ziemlich einfach, aber nur double-checking)
Keine Lösung, aber difftime(givendate, birthdate) / 365.25 zu sein scheint rund 5% schneller als (givendate - birthdate) / 365.25). Könnte nützlich sein im Fall, dass Sie am Ende mit der Arithmetik.
guter Aufruf! -.Date nur Anrufe difftime mehr robust. Noch schneller sollte (unclass(givendate) - unclass(birthdate)) / 365.25 da diese weiter springt der Aufwand difftime.

InformationsquelleAutor Hernando Casas | 2015-06-29

Schreibe einen Kommentar