2016-08-08 18 views
2

Wie zählen Sie die Jahre, seit etwas in R passiert ist? Meine Daten sieht wie folgt aus:Zählen zurück zu den Ereignissen in R

    Year Fatal Non-Fatal 
French Airline 1989 1  1 
French Airline 1990 1  0 
French Airline 1991 0  0 
French Airline 1992 0  1 
French Airline 1993 0  0 
UK Airline  1989 1  1 
UK Airline  1990 0  0 
UK Airline  1991 1  0 
UK Airline  1992 0  0 
UK Airline  1993 0  0 

nach Airline gruppierte, ich möchte eine zusätzliche Spalte haben, die zählt, zurück, wenn der letzte tödliche oder nicht-tödlichen Unfall passiert ist. Der Ausgang würde dann in etwa so aussehen:

    Year Fatal Non-Fatal Since Fatal Since Non-Fatal    
French Airline 1989 1  1   0    0 
French Airline 1990 1  0   0    1 
French Airline 1991 0  0   1    2 
French Airline 1992 0  1   2    0 
French Airline 1993 0  0   3    1 
UK Airline  1989 1  1   0    0 
UK Airline  1990 0  0   1    1 
UK Airline  1991 1  0   0    2 
UK Airline  1992 0  0   1    3 
UK Airline  1993 0  0   2    4 

In einer idealen Welt, die ich auch eine andere Spalte am Ende haben würde, die auf jede Art von Crash zählt zurück, fatal oder nicht-fatal. Wie mache ich es?

+0

In Eingang und Ausgang der 'Fatal‘, ‚Non-Fatal‘ Werte nicht gleich sind. – akrun

+0

Mein schlechtes! Bearbeitet jetzt, natürlich soll es dasselbe sein. – vio

+0

Ist es absichtlich, dass Sie eine längere Zeit ohne fatal mehrere Male zählen, wie Sie nicht-tödlich jedes Mal erhöhen? Z.B. Französisch: 0,0,1,2,3: In einigen Analysen könnte dies Daten über 8 Jahre aussehen - aber es sind 5 Jahre. – Christoph

Antwort

2

Joins und erfordern Version 1.9.7+ des Pakets:

library(data.table) 

# data borrowed from @majom's answer 

d[, sf := 
    d[as.logical(Fatal)][d, on=.(Airline, Year), roll=TRUE, Year-x.Year]] 

d[, sn := 
    d[as.logical(Non_Fatal)][d, on=.(Airline, Year), roll=TRUE, Year-x.Year]] 

d[, sa := 
    d[as.logical(pmax(Fatal, Non_Fatal))][d, on=.(Airline, Year), roll=TRUE, Year-x.Year]] 

die gibt

  Airline Year Fatal Non_Fatal sf sn sa 
1: French_Airline 1989  1   1 0 0 0 
2: French_Airline 1990  1   0 0 1 0 
3: French_Airline 1991  0   0 1 2 1 
4: French_Airline 1992  0   1 2 0 0 
5: French_Airline 1993  0   0 3 1 1 
6:  UK_Airline 1989  1   1 0 0 0 
7:  UK_Airline 1990  0   0 1 1 1 
8:  UK_Airline 1991  1   0 0 2 0 
9:  UK_Airline 1992  0   0 1 3 1 
10:  UK_Airline 1993  0   0 2 4 2 

Alternativ für die letzte: d[, sa := pmin(sf, sn)], wenn Sie bereits diejenigen berechnet haben.

Der Zwang zu logisch ein Hinweis sein sollte, dass diese cols sollte bereits als logische gespeichert werden ...

+1

Danke! Ich bin ein Neuling. Was meinst du mit dem Paket? R? – vio

+0

Oh, ich meinte das data.table-Paket, das Sie in Ihrer Frage getaggt haben. Wenn Sie nicht damit vertraut sind, würde ich vorschlagen, hier zu beginnen: https://github.com/Rdatatable/data.table/wiki/Getting-started Version 1.9.7 ist die aktuelle Entwicklungsversion, mit Installationsanweisungen hier: https://github.com/Rdatatable/data.table/wiki/Installation Oh, oh. Habe gerade bemerkt, dass Majom derjenige war, der diese Frage zu deiner Frage hinzugefügt hat. – Frank

+0

Ist das die Rolle = TRUE, die in 1.9.7 einzigartig ist? – akrun

1

Hier Art und Weise die Variablen durch die Hilfe der cumuluated Summen fatal/nicht-tödliche/irgendwelche Abstürze von Fluggesellschaft zu berechnen:

# Load required package 
library(data.table) 

# Setup data 
d <- fread("Airline Year Fatal Non_Fatal 
French_Airline 1989 1  1 
French_Airline 1990 1  0 
French_Airline 1991 0  0 
French_Airline 1992 0  1 
French_Airline 1993 0  0 
UK_Airline  1989 1  1 
UK_Airline  1990 0  0 
UK_Airline  1991 1  0 
UK_Airline  1992 0  0 
UK_Airline  1993 0  0", header=T) 

# Since fatal calculation 
d[ ,Cumsum.Fatal:=cumsum(Fatal), by=Airline] 
d[Fatal!=1, Since.Fatal:=1:.N, by=list(Airline, Cumsum.Fatal)] 
d[Fatal==1, Since.Fatal:=0] 

# Since non-fatal calculation 
d[ ,Cumsum.Non_Fatal:=cumsum(Non_Fatal), by=Airline] 
d[Non_Fatal!=1, Since.Non_Fatal:=1:.N, by=list(Airline, Cumsum.Non_Fatal)] 
d[Non_Fatal==1, Since.Non_Fatal:=0] 

# Since any (fatal or non-fatal) crash 
d[, Any_Crash:=ifelse(I(Fatal+Non_Fatal)>=1, 1, 0)] 
d[ ,Cumsum.Any_Crash:=cumsum(Any_Crash), by=Airline] 
d[Any_Crash!=1, Since.Any_Crash:=1:.N, by=list(Airline, Cumsum.Any_Crash)] 
d[Any_Crash==1, Since.Any_Crash:=0] 

Der letzte data.table so aussieht:

# > d 
# Airline   Year Fatal Non_Fatal Cumsum.Fatal Since.Fatal Cumsum.Non_Fatal Since.Non_Fatal Any_Crash Cumsum.Any_Crash Since.Any_Crash 
# 1: French_Airline 1989  1   1   1   0    1    0   1    1    0 
# 2: French_Airline 1990  1   0   2   0    1    1   1    2    0 
# 3: French_Airline 1991  0   0   2   1    1    2   0    2    1 
# 4: French_Airline 1992  0   1   2   2    2    0   1    3    0 
# 5: French_Airline 1993  0   0   2   3    2    1   0    3    1 
# 6:  UK_Airline 1989  1   1   1   0    1    0   1    1    0 
# 7:  UK_Airline 1990  0   0   1   1    1    1   0    1    1 
# 8:  UK_Airline 1991  1   0   2   0    1    2   1    2    0 
# 9:  UK_Airline 1992  0   0   2   1    1    3   0    2    1 
# 10: UK_Airline 1993  0   0   2   2    1    4   0    2    2 


UPDATE:

Hier

ist effiziente Art und Weise, wie Sie den Befehl mit freundlicher Genehmigung von Frank (siehe Kommentare) schreiben:

d[, sf := seq(.N)-1L, by=.(Airline, cumsum(Fatal))][, snf := seq(.N)-1L, by=.(Airline, cumsum(Non_Fatal))][, sa := seq(.N)-1L, by=.(Airline, cumsum(pmax(Fatal, Non_Fatal)))][] 

# Airline   Year Fatal Non_Fatal Cumsum.Fatal Since.Fatal Cumsum.Non_Fatal Since.Non_Fatal Any_Crash Cumsum.Any_Crash Since.Any_Crash sf snf sa 
# 1: French_Airline 1989  1   1   1   0    1    0   1    1    0 0 0 0 
# 2: French_Airline 1990  1   0   2   0    1    1   1    2    0 0 1 0 
# 3: French_Airline 1991  0   0   2   1    1    2   0    2    1 1 2 1 
# 4: French_Airline 1992  0   1   2   2    2    0   1    3    0 2 0 0 
# 5: French_Airline 1993  0   0   2   3    2    1   0    3    1 3 1 1 
# 6:  UK_Airline 1989  1   1   1   0    1    0   1    1    0 0 0 0 
# 7:  UK_Airline 1990  0   0   1   1    1    1   0    1    1 1 1 1 
# 8:  UK_Airline 1991  1   0   2   0    1    2   1    2    0 0 2 0 
# 9:  UK_Airline 1992  0   0   2   1    1    3   0    2    1 1 3 1 
# 10: UK_Airline 1993  0   0   2   2    1    4   0    2    2 2 4 2 
+1

Richtig. Meine Antwort wurde aktualisiert. Vielen Dank. – majom

+1

Ich denke nicht, dass Sie das cumsum oder ifelse in einer Spalte speichern müssen, und behandeln Sie Fälle nicht separat mit == und! = 1. Zum Beispiel, 'd [, sf: = seq (.N) -1L, by = . (Fluggesellschaft, cumsum (Fatal))] [, snf: = seq (.N) -1L, durch =. (Fluggesellschaft, cumsum (Non_Fatal))] [, sa: = seq (.N) -1L, durch = . (Airline, Cumsum (pmax (Fatal, Non_Fatal)))] [] scheint es zu tun ...? – Frank

+0

Wahr. Vielen Dank. Ich habe nicht viel über Optimierung nachgedacht, sondern wollte vielmehr die Schritte veranschaulichen, wie man über das Problem denken könnte. Chaining ist immer elegant, aber für Neulinge oft nicht lesbar.Möchten Sie Ihren Ansatz als separate Antwort hinzufügen oder sollte ich sie meiner Antwort hinzufügen und Ihnen Gutschriften geben? – majom