2016-03-29 25 views
3

ich einen Datenrahmen haben - Sie die Probe mit dem folgenden Code neu erstellen können:Datenextraktion/Umformen von einem Datenrahmen in R

df = data.frame(M_id = c(rep(1000,8),rep(1001,8)), Day = c(rep(1,4),rep(2,4),rep(1,4),rep(2,4)), Half_hr = rep(1:4,4) ,Val = c(0.25,0.1,0.2,0.4,0.3,0.6,0.35,0.5,0.15,0.2,0.3,0.5,0.4,0.7,0.45,0.6)) 

Es sieht wie folgt aus:

>df : 

M_id Day Half_hr  Val 
1000 1 1   0.25 
1000 1 2   0.1 
1000 1 3   0.2 
1000 1 4   0.4 
1000 2 1   0.3 
1000 2 2   0.6 
1000 2 3   0.35 
1000 2 4   0.5 
1001 1 1   0.15 
1001 1 2   0.2 
1001 1 3   0.3 
1001 1 4   0.5 
1001 2 1   0.4 
1001 2 2   0.7 
1001 2 3   0.45 
1001 2 4   0.6 

Hier repräsentiert Val in jeder Zeile den Wert für die M_id für diesen Tag in dieser Half_hr (Half_hr: 1,2 ist Stunde 1 und 3,4 ist Stunde 2 und so weiter). Meine tatsächlichen Daten haben so viele IDs und Tage und Val für 48 Half_hrs (für 24 Stunden)

Jetzt möchte ich die Daten für jede Half_hr in jede Stunde für jede M_id für jeden Tag aggregieren.

My Ausgabe wie folgt aussehen:

>df: 

M_id Day Hour_1 Hour_2 
1000 1 0.35 0.6 
1000 2 0.9  0.85 
1001 1 0.35 0.8 
1001 2 0.11 1.05 

Beispiel ist M_id = 1000, Tag = 1, Hour_1 = Val (Half_hr-1 + Half_hr-2) = 0,25 + 0,1 = 0,35. Ähnlich für Hour_2 = val (Half_hr-3 + Half_hr-4) = 0.2 + 0.4 = 0.6

Ich habe dies mit for-Schleifen und sqldf getan, aber es dauerte sehr viel Zeit.

Ich fordere einen optimierten Code als die Daten, die ich verarbeiten muss, hat 1000 M_ids, jeweils für 535 Tage und 48 Half_hrs für jeden Tag (24 Stunden Daten).

Antwort

3

Wir können data.table verwenden. Konvertieren Sie die ‚data.frame‘ auf ‚data.table‘ (setDT(df). Erstellen Sie eine Gruppenvariable mit gl nach dem Gruppieren von „M_id“, „Day“, dann dcast verwenden von ‚long‘ auf ‚breit‘ Format zu konvertieren

library(data.table) 
df1 <- setDT(df)[order(M_id,Day, Half_hr)][, 
     gr:=gl(.N, 2, .N) , .(M_id ,Day)][] 
dcast(df1, M_id+Day~paste0("Hour_", gr), value.var="Val", sum) 
# M_id Day Hour1 Hour2 
#1: 1000 1 0.35 0.60 
#2: 1000 2 0.90 0.85 
#3: 1001 1 0.35 0.80 
#4: 1001 2 1.10 1.05 
+0

Enthält diese 'annimmt Half_hr' bestellt –

+0

@ RomanLuštrik ich, dass früher angenommen, aber nach Ihrem Kommentar' order'ed der Daten – akrun

3

Hier ist eine Lösung in der Basis R transform() verwenden, aggregate() und reshape():

reshape(aggregate(Val~.,transform(df,Hour=(Half_hr-1L)%/%2L+1L,Half_hr=NULL),sum),dir='w',idvar=c('M_id','Day'),timevar='Hour'); 
## M_id Day Val.1 Val.2 
## 1 1000 1 0.35 0.60 
## 2 1001 1 0.35 0.80 
## 3 1000 2 0.90 0.85 
## 4 1001 2 1.10 1.05 
+0

Es funktioniert auch gut, aber vergleichsweise Lösung mit data.table ist schnell für meine Daten. Ich danke dir sehr. –

Verwandte Themen