2016-11-28 1 views
0

Hier mein data.frame:Subset ein bestimmtes Datum (Jahr und Monat) von data.frame

df = read.table(text = 'ID Date 
1  1975-01-01 
2  1980-02-01 
3  1985-05-01 
4  1990-07-01 
5  1990-08-01 
6  1993-01-01 
7  1993-09-01', header = TRUE) 

Ich brauche eine Teilmenge davon erstellen, indem Sie ein bestimmtes Datum (Jahr und Monat) wählen.

Die Termine Ich bin interessiert sind:

dates = c('1980-02', '1990-07', '1993-09') 

und deshalb sollte mein ausgegeben:

ID  Date 
2  1980-02-01 
4  1990-07-01 
7  1993-09-01 

Gibt es eine Möglichkeit, einen eindeutigen Code zu schreiben, der den Trick von df beginnend tun und dates , ohne die Daten im Code manuell hinzuzufügen?

Dank

#### UPDATE

Was passiert, wenn ich mehrere Beobachtungen im selben Monat in df, wie bekommen haben:

df2 = read.table(text = 'ID Date 
1  1975-01-01 
2  1980-02-01 
9  1980-02-01 
3  1985-05-01 
4  1990-07-01 
12  1990-07-01 
16  1990-07-01 
5  1990-08-01 
6  1993-01-01 
7  1993-09-01 
67  1993-09-01', header = TRUE) 

Neue Ausgabe:

ID  Date 
2  1980-02-01 
9  1980-02-01 
4  1990-07-01 
12  1990-07-01 
16  1990-07-01 
7  1993-09-01 
67  1993-09-01 

Dank

+0

Da Ihre Daten standardisiert zu sein scheinen, können Sie 'df [substr (df $ Date, 1,7)% in% dates,]' verwenden. Aber um sicherzugehen, wird die Verwendung von geeigneten Datum-Zeit-Formaten bevorzugt. –

+2

'df [df $ Datum% in% as.Date (paste0 (Datum," - 01 ")),]'. Dies setzt voraus, dass "df $ Date" bereits im Datumsformat ist. – eipi10

+0

vielen dank an alle! –

Antwort

0

Hier sind einige Lösungen. Sie (i) arbeiten mit beliebigen Daten, nicht nur mit denen, die die ersten des Monats sind, (ii) bewahren die Reihenfolge df2 in der Ausgabe, (iii) sind kompakt, dh jeweils eine Zeile und erfordern nicht die mehrfache Erwähnung von df2 .

1) substr Dies verwendet keine Pakete.

subset(df2, substr(Date, 1, 7) %in% dates) 

geben:

ID  Date 
2 2 1980-02-01 
3 9 1980-02-01 
5 4 1990-07-01 
6 12 1990-07-01 
7 16 1990-07-01 
10 7 1993-09-01 
11 67 1993-09-01 

2) Zoo :: wie.yeymon Eine andere Möglichkeit besteht darin, sowohl Date als auch in die Klasse "yearmon" umzuwandeln, was das gleiche Ergebnis liefert. Dieser Code ist ein bisschen schöner, benötigt aber ein Paket.

library(zoo) 
subset(df2, as.yearmon(Date) %in% as.yearmon(dates)) 
0

Acc ording zu den Daten, die Sie die Klasse Date Spalte geteilt haben, ist Faktor. Wir konvertieren sie in Date Klasse und extrahieren Sie den Monat und Jahr Teil und passen Sie es die Vektor, um die Zeile Zahlen von df, die übereinstimmen.

df[match(dates, format(as.Date(df$Date), "%Y-%m")), ] 

# ID  Date 
#2 2 1980-02-01 
#4 4 1990-07-01 
#7 7 1993-09-01 

Gemäß der aktualisierten Frage, wenn wir mehrere Tage, haben wir zu passen %in% das gibt Ihnen die gewünschte Ausgabe verwenden können.

df2[format(as.Date(df2$Date), "%Y-%m") %in% dates, ] 

# ID  Date 
#2 2 1980-02-01 
#3 9 1980-02-01 
#5 4 1990-07-01 
#6 12 1990-07-01 
#7 16 1990-07-01 
#10 7 1993-09-01 
#11 67 1993-09-01 
+0

Hallo, ich habe gerade meine Frage aktualisiert, könntest du bitte einen Blick darauf werfen? danke –

+0

@test Ich habe die Antwort aktualisiert. –

0

Versuchen

S = sapply(dates, function(d) { grep(d, df[,2]) }) 
    df[S,] 
0

als @ eipi10 in den Kommentaren darauf hingewiesen:

df[df$Date %in% as.Date(paste0(dates,"-01")), ] 

das mit meiner Frage aktualisiert gut funktioniert.

Danke

2

Ihre Daten sind als Strings formatiert, so dass sie etwas schwierig zu bearbeiten sind. Im Allgemeinen ist es besser, sie als tatsächliche Datumsobjekte zu formatieren. Dies kann mit the lubridate package erfolgen. Folgendes würde ich tun. Ich verwende rearr Paket für die automatische Typerkennung und purrr für die funktionale Programmierung.

library(pacman) 
p_load(lubridate, readr, purrr) 

df = read_table(
'ID Date 
1  1975-01-01 
2  1980-02-01 
9  1980-02-01 
3  1985-05-01 
4  1990-07-01 
12  1990-07-01 
16  1990-07-01 
5  1990-08-01 
6  1993-01-01 
7  1993-09-01 
67  1993-09-01' 
) 

dates = parse_date_time(c('1980-02', '1990-07', '1993-09'), orders = "Y-m") 

#subset 
df[year(df$Date) %in% year(dates) & month(df$Date) %in% month(dates), ] 

Der Ausgang davon:

# A tibble: 7 × 2 
    ID  Date 
    <int>  <date> 
1  2 1980-02-01 
2  9 1980-02-01 
3  4 1990-07-01 
4 12 1990-07-01 
5 16 1990-07-01 
6  7 1993-09-01 
7 67 1993-09-01 

Also, wir die Daten laden, wie Sie getan haben, aber tun Sie es mit readr automatisch zu haben, um die Daten zu erkennen. Dann unterteilen wir die Zeilen, in denen das Jahr mit einem der Jahre im Objekt übereinstimmt, und der Monat stimmt mit einem der Monate im Objekt überein. Dies gibt die gewünschte Ausgabe.

Vielleicht möchten Sie jedoch nur die Kombinationen, die Sie gaben. So z.B. Jahr 1980 ist nur in Ordnung, wenn es mit Monat 2 auftritt. Wenn ja, ist es ein bisschen komplizierter. Dies könnte auf viele Arten geschehen, aber ich entschied mich für einen funktionalen Ansatz. Dies ist nicht die schnellste Ausführung, aber es ist schnell zu schreiben und sehr flexibel.

#subset stricter 
inclusion_func = function(x, desired_dates) { 
    #loop over each date 
    map_lgl(x, function(date) { 
    any(map_lgl(desired_dates, function(desired_date) { 
     year(date) == year(desired_date) && month(date) == month(desired_date) 
    }) 
    ) 
    }) 
} 

df[inclusion_func(df$Date, dates), ] 

Der Ausgang davon ist das gleiche:

# A tibble: 7 × 2 
    ID  Date 
    <int>  <date> 
1  2 1980-02-01 
2  9 1980-02-01 
3  4 1990-07-01 
4 12 1990-07-01 
5 16 1990-07-01 
6  7 1993-09-01 
7 67 1993-09-01 

Was die Funktion tut, ist eine Schleife über jedes Datum in dem Datenrahmen, und eine Schleife über jedes Jahr/Monat Kombination. Es prüft dann, ob sowohl das Jahr als auch der Monat für diese bestimmte Kombination übereinstimmen. Wenn eine der drei Kombinationen übereinstimmt (daher any), wird TRUE für diese Zeile zurückgegeben.

Verwandte Themen