2016-07-14 14 views
0

Ich versuche, eine elegante Lösung für ein Problem ohne komplexe Teilmenge und/oder Zeile für Zeile Iteration zu finden. Ich werde über das Beispiel erklären:Aggregierte bedingte Anweisungen

# Load data 
df1 <- mtcars 

# Can aggregate with simple math functions i.e. mean or sum 
hp_by_cyl <- aggregate(hp ~ cyl, data=df1, mean) 
> hp_by_cyl 
    cyl  hp 
1 4 82.63636 
2 6 122.28571 
3 8 209.21429 

Ok. Aber in meinen wirklich viel komplexeren Daten möchte ich einen logischen Wert aggregieren - d. H. Wenn x für irgendeine Zeile der Kategorie A wahr ist, dann ist y = 1. Also mein Beispiel zu verlängern ich eine Spalte mit logischen Variable erstellen:

df1$logic <- ifelse(df1$gear==4 & df1$hp < 150, 1, 0) 
# How do I aggregate the logical values levels of cyl to answer yes/no 
# if any car with x cylinders has 4 gears and < 150 hp ? 
# So I want an finished table like this: 
cyl  logic 
4  1 
6  1 
8  0 

Also meine Frage ist, wie das Aggregat zu verwenden (oder alternativ) Befehl eine Tabelle wie folgt zu produzieren?, d. H. Den logischen Status zu kombinieren, nicht den numerischen Wert?

Ich brauche auch mit codierten fehlenden Werten auch in der Realität zu tun, so dass die Komplexität zu emulieren ich einen der Logik der mache 99:

df1[5, ]$logic <- 99 

Wenn für ein gegebenes Niveau von cyl ein Wert 1 ist, die 99 kann ignoriert werden - wenn jedoch alle anderen 0 sind, dann sollte das Aggregat 99 sein.

Entschuldigung, wenn es eine einfache Antwort gibt, sehe ich nicht in meinen realen Daten, es scheint entmutigend. Ich könnte eine böse Lösung aushacken, aber ich weiß, dass es sehr langsam sein wird und ich einen 14000 X 140 großen Datensatz habe. Vielen Dank im Voraus alles.

+3

Was ist das Problem? – Carl

+0

Ich habe keine Ahnung, wie man es programmiert, um die Übersichtstabelle zu erstellen, die ich möchte. Bearbeitet für Klarinette – user2498193

Antwort

1

Erstens, nicht mit 0/1/99 stören, lassen Sie es nur wahr/falsch/NA.

df1$logic <- df1$gear==4 & df1$hp < 150 

Dann aggregieren nur mit any oder tapply.

aggregate(logic ~ cyl, data=df1, any) 
## cyl logic 
## 1 4 TRUE 
## 2 6 TRUE 
## 3 8 FALSE 

with(df1, tapply(logic, cyl, any)) 
## 4  6  8 
## TRUE TRUE FALSE 

Das plyr Paket, speziell die ddply Funktion, ist eine weitere Option, dass viele Menschen intuitiver finden.

library(plyr) 
ddply(df1, ~cyl, summarize, isany = any(gear==4 & hp < 150)) 
## cyl isany 
## 1 4 TRUE 
## 2 6 TRUE 
## 3 8 FALSE 
+0

Hallo Aaron. Hmm, das könnte funktionieren. Ich werde es versuchen und dich wissen lassen. Ändern der 0/1/99 könnte schwierig sein, da Sachen davon abhängen und ich muss vielleicht zwischen tatsächlichen NAs und codierten Missings unterscheiden. Ich habe auch eine andere Lösung gefunden, aber sie ist nicht so sauber. 'Ergebnis <- Aggregat (Logik ~ Zyl, Daten = df1, Summe); Ergebnis <- ifelse (Ergebnis> 99, 1, Ergebnis) '. Dies beruht darauf, dass es natürlich keine 99 1 gibt! Also, wie ich sage nicht so sauber wie deine – user2498193

+0

Sie sollten mit Ihren verschiedenen Arten von fehlenden befassen, wenn Sie Ihre logische Spalte erstellen, so dass die logische Spalte selbst WAHR/FALSCH/NA sein kann. – Aaron

+0

Wenn ich vorher keine Fehler habe sollte es nicht entstehen ... Also versuche deine Methode in Live Daten aber Ergebnis ist '.Primitive (" any ")' für jede Gruppierungsvariable. Ich bin mir nicht sicher, warum ich keinen offensichtlichen Grund sehe, aber ich erforsche es immer noch. EDIT: ok, repariere es, indem ich 'function (x)' herausnehme, die ich aus irgendeinem Grund verlassen habe. Ok danke das löst mein Problem !! – user2498193

2

Ich denke, das ist das, was man wollte:

aggregate(hp~cyl,data=mtcars,function(x) ifelse(mean(x)<150,1,0)) 

edit: dplyr ist dein Freund:

mtcars %>% group_by_(~cyl) %>% summarise_(logic=~ifelse(mean(hp)<150 & sum(wt)>3,1,0)) 

Dies hat eine komplexere logische Aussage so hoffentlich das hilft. aggregate ist nicht der beste Ansatz, wenn Sie mehr als 2 Variablen gleichzeitig verarbeiten möchten.

+0

Arbeitet im Spielzeugbeispiel - wird die Hauptdaten einchecken und mit Bestätigung/Komplikationen zurückkommen! Danke, dass Sie beide Ihre Frage und Ihre Antwort geklärt haben! – user2498193

+2

'as.integer (mean (x) <150)' könnte 'ifelse()' für binäre Ergebnisse ersetzen und ist effizienter. –

+0

Eigentlich nein - schau es nochmal an - das ist nicht dasselbe. Sie haben durchschnittlich einen Test gemacht. Das funktioniert, weil das Beispiel grob ist, aber nicht wie ich es oben darstellte, wo ich absichtlich eine Spalte mit logischen Werten aufstelle. In den realen Daten ist die Spalte "logic" das Ergebnis einer ganzen Menge Arbeit und kann nicht vereinfacht werden, wie Sie es hier getan haben. – user2498193