GNU R: Umgang mit Datensätzen (Erstellen, Auswählen und Filtern)

Aus Wikibooks

Datensatzerstellung[Bearbeiten]

Angenommen wir haben eine Erhebung durchgeführt. Von einer Anzahl Menschen (Untersuchungseinheiten) interessierte uns Name, Geschlecht, Lieblingsfarbe, und Einkommen (Variablen). Vielleicht haben wir ihnen einen Fragebogen übergeben oder die entsprechenden Angaben in einer Liste notiert. Jetzt wollen wir die Daten übernehmen. Wer zuvor schon mit anderer Statistiksoftware gearbeitet hat, kann sich diese Daten vermutlich schon als geordnete Liste vorstellen (vgl. Anwendungsbeispiel 4).

Typischerweise repräsentiert dabei jede Zeile eine Untersuchungseinheit, während die Variablen in den Spalten stehen:

Name Geschlecht Lieblingsfarbe Einkommen
Hans männlich grün 1233
Caro weiblich blau 800
Lars intersexuell gelb 2400
Ines weiblich schwarz 4000
Samira weiblich gelb 899
... ... ... ...

Diese Form der Datenrepräsentation bewerkstelligt man in R am leichtesten über einen sogenannten data.frame. Um die Daten des Beispiels zu erfassen, können wir z.B. so einen neuen Datensatz erstellen, der die Variablen enthält:

bsp4 <- data.frame( Name=character(), Geschlecht=factor(), Lieblingsfarbe=factor(), Einkommen=numeric() )

Dem Objekt bsp4 wird damit ein data.frame zugewiesen, der aus vier (noch leeren) Vektoren (Name, Geschlecht, Lieblingsfarbe und Einkommen) besteht. Diese sollen unsere Variablendaten enthalten und haben entsprechende Datenmodi: Einkommen ist numerisch (numeric()), Geschlecht ist kategorial und wird als factor repräsentiert, usw.

R kennt verschiedene Möglichkeiten der Dateneingabe (-> Import). Wer eine Version mit graphischem User-Interface verwendet, kann Daten in einem eigenen Editor eingeben:

bsp4 <- data.entry(bsp4)               
                                      # ersetzt bsp4 durch editierte version von bsp4
                                      # Aufruf ohne Zuweisung würde Veränderungen nicht speichern 
Der Data Editor hat in der gezeigten OS X-Version einige wenige Funktionen. Durch Klicken des dritten Buttons kann eine Zeile eingefügt werden. Klicken in die Felder ermöglicht dann die Eingabe. Tabulatortaste springt zum nächsten Feld.

Beendet wird die Dateneingabe einfach durch Schließen des Fensters.

Da das Interessante an Datensätzen aber wohl eher nicht deren Eingabe ist, können wir uns diese Arbeit sparen:

  • Wenn Sie bereits das Paket wikibooks installiert und geladen haben, steht der Datensatz mit dem Befehl data(bsp4) zur Verfügung.
  • Andernfalls können die obigen Daten durch Kopieren der folgenden Zuweisung in die Eingabezeile direkt übernommen werden:

bsp4 <- structure(list(Name = c("Hans", "Caro", "Lars", "Ines", "Samira", "Peter", "Sarah"), Geschlecht = structure(c(2L, 3L, 1L, 3L, 3L,2L, 3L), .Label = c("intersexuell", "maennlich", "weiblich"), class = "factor"),Lieblingsfarbe = structure(c(3L, 1L, 2L, 4L, 2L, 3L, 1L), .Label = c("blau","gelb", "gruen", "schwarz"), class = "factor"), Einkommen = c(1233,800,2400,4000,899,1100,1900)), .Names = c("Name","Geschlecht", "Lieblingsfarbe", "Einkommen"), row.names = c(NA,7L), class = "data.frame")

Tipp: Bei diesem - hier nicht bedeutsamen - Code handelt es sich um die interne Repräsentation eines data.frame in R, die für beliebige Objekte mit der Funktion deparse(x) ausgegeben werden kann.

In jedem Fall sollte nun das Objekt bsp4 die obigen Daten enthalten:

 > bsp4
    Name   Geschlecht Lieblingsfarbe Einkommen
1   Hans    maennlich          gruen      1233
2   Caro     weiblich           blau       800
3   Lars intersexuell           gelb      2400
4   Ines     weiblich        schwarz      4000
5 Samira     weiblich           gelb       899
6  Peter    maennlich          gruen      1100
7  Sarah     weiblich           blau      1900

Referenzierung (Auswahl von Variablen oder Fällen)[Bearbeiten]

Die Referenzierung von data.frames erfolgt allgemein durch den Objekt-/ Datensatznamen gefolgt von eckigen Klammern nach der Regel:
datensatzname  [ Zeile(n) , Spalte(n) ]


Auswählen von Variablen (spaltenweise)[Bearbeiten]

Angenommen wir interessieren uns zunächst nur für die Variable Geschlecht. Dann geht es uns nur um die zweite Spalte.

> bsp4 [,2]
[1] maennlich    weiblich     intersexuell weiblich     weiblich     maennlich    weiblich
Levels: intersexuell maennlich weiblich

Wir erhalten die gemachten Angaben zu Geschlecht und – da es sich um einen factor handelt – die möglichen Ausprägungen dieser Variable (Levels:...). Eine andere, gleichwertige Möglichkeit funktioniert folgendermaßen:

> bsp4$Geschlecht
[1] maennlich    weiblich     intersexuell weiblich     weiblich     maennlich    weiblich
Levels: intersexuell maennlich weiblich

Auswählen von Fällen (zeilenweise)[Bearbeiten]

data.frames können sehr viele Fälle umfassen. Oft ist es deshalb sinnvoll, sich nur einen bestimmten Fall anzusehen, z.B. den dritten:

> bsp4 [3,]
  Name   Geschlecht Lieblingsfarbe Einkommen
3 Lars intersexuell           gelb      2400

Erweiterte Referenzierung[Bearbeiten]

Zusätzlich zu obiger Konvention können zwei weitere Verfahren zum Einsatz kommen:

  • Minuszeichen (-) schließen Zeilen oder Spalten aus.
  • Wenn Vektoren in den eckigen Klammern angegeben werden, werden alle darin angegebenen positiven Zahlen ausgewählt und alle negativen ausgeschlossen.

Wenn wir für die Fälle 1,4,6 alle Variablen mit Ausnahme des Geschlechts ausgeben wollen, lautet die Referenzierung somit:

> bsp4[c(1,4,6), -2 ]
    Name Lieblingsfarbe Einkommen
1   Hans          gruen      1233
4   Ines        schwarz      4000
6  Peter          gruen      1100

Referenzierungen können ebenso in Zuweisungen verwendet werden.

Angenommen wir bemerken nachträglich, dass die Einkommensangabe von Ines falsch war. Wenn sie 3000 statt 4000 Euro zur Verfügung hat, können wir das folgendermaßen korrigieren.

> bsp4[4,4] <- 3000
> bsp4[4,]
 Name Geschlecht Lieblingsfarbe Einkommen
4 Ines   weiblich        schwarz      3000

Auswahl von Fällen mittels "Wildcard"[Bearbeiten]

Man kann die Fälle auch mittels "Wildcard" auswählen, indem man sich der Funktionen grep, regexpr- und which bedient. Angenommen, wir möchten diejenigen Fälle haben, deren Lieblingsfarbe mit "bl" beginnt, so lautet der passende Befehl:

bsp4[grep("bl",bsp4$Lieblingsfarbe),]

oder

bsp4[which((regexpr("bl",bsp4$Lieblingsfarbe))==1),]


Möchten wir diejenigen Fälle haben, in deren Vornamen ein "a" enthalten ist, lautet der Befehl:

bsp4[grep(".*a.*",bsp4$Name),]

oder

bsp4[which((regexpr(".*a.*",bsp4$Name))==1),]

".*" ist ein so genannter "regulärer Ausdruck" (engl. "regular expression") und definiert hierbei unsere gewünschte Wildcard. Für weitere Optionen siehe regexpr.

Filtern von Daten: Teilgruppen und bedingte Ausgabe[Bearbeiten]

In der Praxis sind wir oft daran interessiert, Teilgruppen zu bilden.

Eine Frage könnte etwa sein, inwieweit sich die Einkommen von Männern und Frauen in unserem Bekanntenkreis unterscheiden.

Die Funktion subset (x,...)[Bearbeiten]

Eine einfache Möglichkeit Teilgruppen auszuwählen bietet die Funktion subset (x,bedingung_von_x).

> subset(bsp4,bsp4$Geschlecht=="weiblich")
    Name Geschlecht Lieblingsfarbe Einkommen
2   Caro   weiblich           blau       800
4   Ines   weiblich        schwarz      3000
5 Samira   weiblich           gelb       899
7  Sarah   weiblich           blau      1900

Wir interessieren uns nur für das Einkommen der Frauen:

> subset(bsp4$Einkommen,bsp4$Geschlecht=="weiblich")
[1] 800  3000 899  1900

Wenn bsp4 eine größere Fallzahl umfassen würde, wäre diese Liste viel zu lang. Wir würden für einen ersten Eindruck über die Einkommensunterschiede auf das arithmetische Mittel ausweichen:

> mean(subset(bsp4$Einkommen,bsp4$Geschlecht=="weiblich"))
[1] 1649.75                                       # bzw. 1899.75 falls Ines Einkommen=4000
> mean(subset(bsp4$Einkommen,bsp4$Geschlecht=="maennlich"))
[1] 1166.5

Dasselbe Ergebnis lässt sich durch Definition von Teilgruppen erzielen:

> frauen <- subset(bsp4,bsp4$Geschlecht=="weiblich")
> maenner <- subset(bsp4,bsp4$Geschlecht=="maennlich")
> mean(frauen$Einkommen)
[1] 1649.75
> mean(maenner$Einkommen)
[1] 1166.5

Bedingte Referenzierung[Bearbeiten]

Das gleiche Ergebnis wie bei der Benutzung der Funktion subset kann u. U. einfacher durch bedingte Referenzierung erreicht werden. Entsprechend der Auswahl von Fällen (Zeilen) und Variablen (Spalten) durch Nummern in eckigen Klammern kann auch eine Teilgruppe ausgewählt werden, wenn an Stelle von Nummern logische Bedingungen angegeben werden:

datensatzname [ Zeilenbedingung , Spaltenbedingung


Wenn wir z. B. nur die Frauen mit Einkommen über 1500 EUR auswählen wollen, so erreichen wir das folgendermaßen:

> bsp4 [(bsp4$Geschlecht=="weiblich") & (bsp4$Einkommen>1500) ,]

Referenziert werden alle Zeilen (Fälle), für die die beiden obigen Bedingungen gelten (die mit dem Operator & (logisches UND) verknüpft wurden). Entsprechend erhalten wir die Ausgabe:

   Name Geschlecht Lieblingsfarbe Einkommen
4  Ines   weiblich        schwarz      4000                                                                                                                              
7 Sarah   weiblich           blau      1900  
Tipp: Das Komma hinter den Bedingungen ist notwendig, da wir angeben müssen, dass wir mit der Bedingung (wie zumeist) Fälle auswählen wollen. Stünde das Komma vor der Bedingung, so würden wir versuchen mit dieser Bedingung bestimmte Spalten (Variablen) zu selektieren.


Filtern doppelter Einträge[Bearbeiten]

Mit Hilfe der Funktion duplicated() kann ein Datensatz nach doppelten Einträgen durchsucht werden. duplicated gibt hierbei für jede Zeile den Wert "TRUE" oder "FALSE" zurück.

Zunächst erzeugen wir testweise Duplikate in unser Objekt bsp4:

bsp4 <- rbind(bsp4,bsp4) # wir verdoppeln die Einträge
duplicated(bsp4)


In Kombination mit der Funktion which() werden die Zeilnennamen der doppelten Einträge ausgegeben:

which(duplicated(bsp4))

Des weiteren lässt sich diese Kombination auch als Argument zur Zeilendarstellung verwenden:

bsp4[which(duplicated(bsp4)),]

Die Ausgabe von duplicated lässt sich umkehren, wenn ein Ausrufezeichen vorangestellt wird:

bsp4[which(!duplicated(bsp4)),]


Dasselbe Ergebnis erhält man auch über die Funktion unique(), welche alle unterschiedlichen Einträge eines Datensatzes genau einmal anzeigt.

duplicated und unique können nicht nur auf ein gesamtes Objekt, sondern auch auf einzelne Variablen angewendetet werden, z.B.

unique(bsp4$Name)
duplicated(bsp4$Geschlecht)

Hinzufügen / Berechnen neuer Variablen[Bearbeiten]

Angenommen wir wollen eine neue Variable zu unserem Datensatz hinzufügen, die z.B. den Dollarwert der ermittelten Einkommen enthält. Am 8. Juni 2007 erhielt man im Tausch gegen einen Euro 1.34826 US$. Somit errechnen sich die Einkommen ausgedrückt in US$ als:

> bsp4$Einkommen * 1.34826
[1] 1662.405 1078.608 3235.824 5393.040 1212.086 1483.086 2561.694

Mit Hilfe der Funktion cbind ("bind" = engl. verbinden; "c" für column = engl. Spalte ) kann dieser Vektor zum Datensatz als weitere Spalte (Variable) hinzugefügt werden:

bsp4 <- cbind ( bsp4 , "Einkommen (USD)"= bsp4$Einkommen*1.34826 )

Der bisherige Datensatz bsp4 wird ersetzt durch die spaltenweise Verbindung von bsp4 und der neu berechneten Variable "Einkommen (USD)":

> bsp4[1,]
  Name Geschlecht Lieblingsfarbe Einkommen Einkommen (USD)                                                                                                               
1 Hans  maennlich          gruen      1233        1662.405


Hinzufügen neuer Fälle[Bearbeiten]

mittels Daten-Editor[Bearbeiten]

Der folgende Befehl öffnet unser Objekt bsp4 im Daten-Editor. So können weitere Fälle "von Hand" hinzugefügt werden:

bsp4 <- data.entry(bsp4)

mittels rbind[Bearbeiten]

Unserem Datensatz bsp4 soll ein weiterer Fall hinzugefügt werden:

Jörg    maennlich    blau   18000      24268.68

Die vielleicht denkbare Methode

bsp4 <- rbind(bsp4, c("Jörg", "maennlich", "blau", 18000, 24268.68)) # liefert NICHT das gewünschte Resultat!!!

liefert nur auf den ersten Blick hin das gewünschte Resultat. Die Zeile ist zwar dem Frame hinzugefügt worden, aber die Struktur des Frames wurde "zerschossen". Dies wird sichtbar, wenn wir versuchen mit den Werten der Spalte "Einkommen" zu rechnen. Versuchen wir mal, das jeweilige Einkommen mit 12 zu multiplizieren:

bsp4$Einkommen * 12

Dieser Befehl schlägt fehl, und die Fehlermeldung sagt uns, dass es sich bei der Spalte "Einkommen" nicht mehr um numerische Werte handelt. Und tatsächlich,

class(bsp4$Einkommen)

liefert als Antwort "character". Schuld daran ist die Funktion c, mit derer wir die neue Zeile innerhalb des rbind-Befehls angegeben haben.

  • Unser Datenframe ist eine Liste mit Variablen unterschiedlicher modes (character, factor und numeric).
  • Der Befehl c definiert hingegen eine Liste, die nur einen Mode haben kann. Innerhalb unseres Ausdrucks "c("Jörg", "maennlich", "blau", 18000, 24268.68)" sind jedoch die modes character (zu erkennen an den Anführungszeichen) und numeric enthalten.
  • Da dies nicht geht, ermittelt R automatisch einen "Gesamt"-Mode aus dem komplexesten Vektorelement, in diesem Fall "character".
  • Somit sind alle Werte innerhalb des c-Ausdrucks vom Typ character
  • Durch die Verknüpfung mit dem Datenframe myframe geschieht dieser Prozess nun erneut: Die Spalte "Einkommen" kann auch nur einen Mode besitzen. Zunächst ist dieser noch numeric. Durch den oben verwendeten rbind-Ausdruck wird eine Variable vom Typ character hinzugefügt.
  • Da dies auch hier wieder nicht geht, ermittelt R wieder automatisch einen "Gesamt"-Mode aus dem komplexesten Vektorelement für die Spalte "Einkommen", in diesem Fall wieder "character".


Die Lösung:

Und wie geht das dann?

Wir verwenden zunächst an Stelle von c die Funktion data.frame, da hier sehr wohl unterschiedliche modi verwendet werden dürfen. Allerdings können wir leider keinen "Einzeiler" verwenden:

bsp4 <- rbind(bsp4, data.frame("Jörg", "maennlich", "blau", 18000, 24268.68)) # geht auch nicht :(

Der Befehl schlägt mit der Fehlermeldung fehl, die Spalten-Namen würden nicht zueinander passen. Daher verwenden wir die Funktion list:

# DIE LÖSUNG:
bsp4 <- rbind(bsp4, list("Jörg", "maennlich", "blau", 18000, 24268.68))

So geht es.

Umbenennen von Variablen[Bearbeiten]

Der Name der im vorhergehenden Abschnitt neu erstellten Variable enthält Leerzeichen und die Sonderzeichen "(" und ")" . Dies dient der Übersichtlichkeit, ist aber generell eher nicht empfehlenswert, da wir den Variablennamen bei der Referenzierung dann immer in Anführungszeichen setzen müssen ( bsp4$"Einkommen (USD)" ). Somit bietet sich eine Umbenennung an. Zugang zu den Variablennamen eines Datensatzes ermöglicht die Funktion names(), die diese als Vektor zurückgibt:

> names(bsp4)
[1] "Name"            "Geschlecht"      "Lieblingsfarbe"  "Einkommen"       "Einkommen (USD)"

Umbenennung von Variablen funktioniert durch eine Neuzuweisung des Vektors names(bsp4) für das Vektorelement des alten Namens:

names(bsp4)[names(bsp4)=="Einkommen (USD)"] <- "EinkommenUSD"

Eine andere Möglichkeit bietet sich mit Hilfe der Funktion gsub, die bestimmte Zeichen eines character-Vektors durch andere Zeichen ersetzt. Dadurch lassen sich auch mehrere Variablen gleichzeitig umbenennen:

> gsub("Ein","Zwei",names(bsp4))
[1] "Name"             "Geschlecht"       "Lieblingsfarbe"   "Zweikommen"       "ZweikommenUSD"
> names(bsp4) <- gsub("Ein","Zwei",names(bsp4))

Mit dieser Anweisung wurde der gesamte Namensvektor durch die modifizierten Version ersetzt:

> bsp4[1,]
    Name   Geschlecht Lieblingsfarbe Zweikommen ZweikommenUSD
1   Hans    maennlich          gruen       1233      1662.405

Löschen von Variablen[Bearbeiten]

Die Löschung einer Variablen aus einem Datensatz lässt sich am einfachsten folgendermassen erreichen:

bsp4$Name <- NULL

Diese Anweisung weißt der Variable "Name" das NULL-Objekt zu, welches eine Liste der Länge 0 repräsentiert. Objekte der Länge Null werden aus einem data.frame automatisch entfernt und somit ist die Variable gelöscht.

Wenn mehrere Variablen gelöscht werden sollen, bietet sich folgende Variante an:

bsp4 <- bsp4[,-c(1,2)]

Sortieren von Datensätzen[Bearbeiten]

Datensätze lassen sich nach beliebigen Kriterien sortieren, wofür besonders das Funktionspaar sort und v.a. order geeignet ist. Angenommen wir wollen bsp4 nach dem Einkommen sortieren. sort ordnet metrische Vektoren in aufsteigender Reihenfolge.

> sort(bsp4$Einkommen)                                                                                                                                             
[1]  800  899 1100 1233 1900 2400 4000

Allerdings wollen wir keinen Vektor sortieren, sondern den gesamten Datensatz. Dies bewerkstelligen wir über den Umweg der numerischen Indize der Fälle (Zeilen). order gibt als Ergebnis einen Vektor zurück, der die Stelle enthält, an der die mit sort umsortierten Vektorelemente ursprünglich waren.

> order(bsp4$Einkommen)                                                                                                                                            
[1] 2 5 6 1 7 3 4 

Diese Information lässt sich für Datensätze auch folgendermaßen lesen: Der 2. Fall (Caro) hat das niedrigste Einkommen, das zweitniedrigste Einkommen hat der 5. Fall (Samira), usw. Diesen geordneten Indexvektor kann man nun entsprechend den obigen Referenzierungsregeln verwenden, um den Gesamtdatensatz sortiert auszugeben.

> bsp4[order(bsp4$Einkommen), ]                                                                                                                               
    Name   Geschlecht Lieblingsfarbe Einkommen                                                                                                                           
2   Caro     weiblich           blau       800                                                                                                                           
5 Samira     weiblich           gelb       899                                                                                                                           
6  Peter    maennlich          gruen      1100                                                                                                                           
1   Hans    maennlich          gruen      1233                                                                                                                           
7  Sarah     weiblich           blau      1900                                                                                                                           
3   Lars intersexuell           gelb      2400                                                                                                                           
4   Ines     weiblich        schwarz      4000  

Ein weiteres Beispiel soll die Sortierung nach mehreren Kriterien verdeutlichen. Angenommen wir wollen zunächst nach Geschlecht und innerhalb der Geschlechtergruppen als 2. Sortierungsregel nach dem Einkommen sortieren. Hierzu werden Variablen, in der Reihenfolge die der "Sortierungs-Hierarchie" entspricht, hintereinander order übergeben. Für die nominale Variable Geschlecht liefert order eine alphabetische Sortierung. Somit kann der nach beiden Bedingungen sortierte Datensatz ausgeben werden:

>  bsp4[order(bsp4$Geschlecht, bsp4$Einkommen), ]                                                                                          
    Name   Geschlecht Lieblingsfarbe Einkommen                                                                                                                           
3   Lars intersexuell           gelb      2400                                                                                                                           
6  Peter    maennlich          gruen      1100                                                                                                                           
1   Hans    maennlich          gruen      1233                                                                                                                           
2   Caro     weiblich           blau       800                                                                                                                           
5 Samira     weiblich           gelb       899                                                                                                                           
7  Sarah     weiblich           blau      1900                                                                                                                           
4   Ines     weiblich        schwarz      4000

Gruppierung von Variablen[Bearbeiten]

Angenommen uns interessiert der mittlere Wert des Einkommens abhängig von der Geschlechtsgruppe. Mit der Funktion tapply(VARIABLE, GRUPPENVARIABLE, FUNKTION) ist dies besonders einfach möglich:

 > tapply(bsp4$Einkommen,bsp4$Geschlecht,mean)                                                                                                                                
 intersexuell    maennlich     weiblich                                                                                                                                       
      2400.00      1166.50      1899.75 

Übungsaufgaben[Bearbeiten]

  1. Lassen Sie sich die zweite und fünfte Zeile von bsp4 ausgeben.
  2. Lassen sie nur die Namen der Personen ausgeben, deren Lieblingsfarbe "gelb" ist.
  3. Welchen Namen und welches Geschlecht hat die Person mit dem niedrigsten Einkommen? (Benutzen sie hierzu die Funktion rank(variable), die für eine gegebene Variable den Rang in einer aufsteigend geordneten Liste liefert.)


Lösung der Aufgaben[Bearbeiten]

Inhaltsverzeichnis[Bearbeiten]