Wenn man RStudio startet, beginnt man einen R-Session. Man beendet einen R-Session mit
q()
Vorsicht! Entweder schließt sich RStudio, ohne zu fragen (wenn nichts im sogenannten workspace ist), oder die Frage “Save workspace image to ~/.RData? [y/n/c]:” mit “n” beantworten. Einfacher: RStudio über das gewöhnliche Symbol zum schließen eines Programms beenden. Auch dann werden Sie gefragt, ob ein “Workspace image” gespeichert werden soll oder nicht (meistens wollen Sie das NICHT, denn dieses Image wird bei jedem Start von RStudio/R! geladen.)
Wir werden im Laufe des Semesters öfters Daten in R importieren und von R exportieren müssen. Erzeugen Sie dafür ein Verzeichnis auf Ihrer Festplatte und geben Sie den Pfad von diesem Verzeichnis in " " ein in R.
# z.B. den Ordner "R" in "/Users/reubold/Documents/" anlegen, und dann
pfad = "/Users/reubold/Documents/R"
Vergewissern Sie sich, dass dieses Objekt mit dem erwünschten Pfad existiert (aber nicht, dass der angegebene Pfad stimmt):
ls()
## [1] "pfad"
pfad
## [1] "/Users/reubold/Documents/R"
So bestätigen Sie, dass das Verzeichnis auf Ihrer Festplatte tatsächlich existiert (die Antwort muss TRUE
sein):
dir.exists(pfad)
## [1] TRUE
Dies gilt nur, wenn es um einen lokalen Ordner geht. Man kann auch “Pfade” angeben, die in Wirklichkeit eine Webadresse in Form einer URLs (Uniform Resource Locator) sind.
Wir werden öfters sogenannte ‘Data-Frames’ aus einer Webseite (Tabellen als Textdateien) laden. Hier wird der Pfad dieser Webseite festgelegt:
pfadu = "http://www.phonetik.uni-muenchen.de/~jmh/lehre/Rdf"
Jetzt RStudio beenden: antworten Sie nur dieses eine Mal ‘Save’ auf die Frage ‘Save workspace image to ~/.RData?’. Dies soll das einzige Mal sein, in dem diese Frage mit ‘Save’ beantwortet wird: sonst in Zukunft immer ‘Don’t Save’.
Nun RStudio bitte wieder starten, und verifizieren, dass “pfad” und “pfadu” existieren:
ls()
## [1] "pfad" "pfadu"
Ab jetzt können wir Dateien aus pfad bzw. pfadu einlesen, z.B.:
read.table(file.path(pfadu, "ai.txt"))
## F1 Kiefer Lippe
## 1 773 -25.47651 -24.59616
## 2 287 -27.02695 -26.44491
## 3 1006 -27.24509 -27.59161
## 4 814 -26.05803 -27.17365
## 5 814 -26.15489 -25.93095
## 6 806 -26.37281 -24.44872
## 7 938 -27.35341 -27.22650
## 8 1005 -27.98772 -28.26871
## 9 964 -26.27536 -27.05215
## 10 931 -26.09928 -26.54016
## 11 926 -26.40012 -26.83834
## 12 556 -25.73544 -27.21908
## 13 707 -25.84109 -23.44627
## 14 829 -26.37598 -25.23304
## 15 927 -27.47505 -27.64328
## 16 951 -26.68685 -25.63057
## 17 775 -25.79928 -23.68594
## 18 938 -27.18105 -25.28667
## 19 986 -27.75178 -27.70719
## 20 888 -25.99100 -26.84534
## 21 988 -26.27380 -28.26909
## 22 650 -26.50057 -24.31192
## 23 1026 -27.10303 -24.64248
## 24 992 -28.41081 -28.30641
## 25 896 -26.57372 -25.69383
Zur Erläuterung:
file.path(pfadu, "ai.txt") #erzeugt einen neuen Pfad, indem an den alten 'pfadu' ein '/' und "ai.txt" angehängt wird
## [1] "http://www.phonetik.uni-muenchen.de/~jmh/lehre/Rdf/ai.txt"
read.table()
liest eine Textdatei in Form einer Tabelle als data.frame ein.
Anstelle von Befehlen wie ls()
, read.table()
usw. können Sie auch RStudio nutzen: in einem Ihrer Panels finden Sie ‘Environment’; dort sind alle Objekte aufgelistet, so wie sie in R
(d.h. in der Console von RStudio) durch ls()
aufgelistet werden. Unter Environment finden Sie auch Buttons zum öffnen, importieren, und speichern von Daten. Sie können dort auch Objekte löschen (Besensymbol). Um einzelne Objekte zu löschen, müssen Sie unter Environment rechts oben den Punkt ‘list’ zu ‘grid’ ändern, dann sehen Sie die Objektliste mit checkboxes angezeigt. Markieren Sie die gewünschten Objekte, und führen Sie anschließend die gewünschte Aktion (z.B. löschen, speicher etc.) durch!
Ein neues Objekt wird mit ‘=’ (assign) oder ‘<-’ erzeugt.
# Es gibt numerische Objekte
x = 3
y <- 4
ls()
## [1] "pfad" "pfadu" "x" "y"
# Und auch Schriftzeichen-Objekte in ""
z = "etwas"
Wenn Sie den Inhalt des Objektes sehen wollen, können Sie einfach den Objekt-Namen eingeben:
x
## [1] 3
Neue Objekte mit dem selben Inhalt erzeugen Sie mit:
x = y = z = 4
Objekte werden in R einfach überschrieben, und zwar (oftmals leider) ohne Warnmeldung:
y = 4
y
## [1] 4
y ="Phonetik"
y
## [1] "Phonetik"
Objekte werden am besten mit save()
gespeichert. Hier ist “etwas” irgendein beliebiger Name. Wir brauchen keine Dateiendung. Wenn wir aber wollen, das die erzeugte Datei später per Doppelclick in R geladen werden kann, sollten wir die Dateiendung “.RData” hinzufügen.
Alles, was gespeichert werden soll, muss unter “list” angegeben werden - im vorliegenden Fall ist das einfach alles. Der Befehl tut also das gleiche, als würden wir R schließen, und auf die Frage “Save workspace image to ~/.RData? [y/n/c]:” mit “y” antworten:
save(list = ls(), file = file.path(pfad, "etwas.RData"))
save(list = ls(), file = file.path(pfad, "etwas"))
Dann q()
(oder einfach RStudio schließen) und (immer) mit n
beantworten - siehe 0.02.
Einfacher geht das wieder in RStudio selbst: einfach unter environment auf das Diskettensymbol clicken.
attach()
bzw. load()
RStudio/R starten und dann:
attach(file.path(pfad, "etwas"))
## The following objects are masked _by_ .GlobalEnv:
##
## pfad, pfadu, x, y, z
Hier ist “etwas” der Name in ‘0.04’ oben. Dann sind die Objekte wieder da…
x
## [1] 4
y
## [1] "Phonetik"
Allerdings sehen wir sie nicht aufgelistet, wenn wir
ls()
## [1] "pfad" "pfadu" "x" "y" "z"
eingeben.
Alle in einer R-Session ‘attach’-ten Objektlisten und Libraries (“packages”, dazu später mehr) sind durch search()
vorhanden:
search()
## [1] ".GlobalEnv"
## [2] "file:/Users/reubold/Documents/R/etwas"
## [3] "package:stats"
## [4] "package:graphics"
## [5] "package:grDevices"
## [6] "package:utils"
## [7] "package:datasets"
## [8] "package:methods"
## [9] "Autoloads"
## [10] "package:base"
Hier sehen wir, dass unser Obkektliste (mit “pfad”,“pfadu”,“x”,“y”,“z”) an zweiter Stelle ist.
Jeder Library, aber auch Objektliste kann mit ‘detach()’ wieder entfernt werden.
detach(2)
search()
## [1] ".GlobalEnv" "package:stats" "package:graphics"
## [4] "package:grDevices" "package:utils" "package:datasets"
## [7] "package:methods" "Autoloads" "package:base"
Die Objekte sind daher nicht mehr vorhanden:
x
# Error: object 'x' not found
Alternative: load()
: entweder doppelclicken auf “etwas.RData”" oder:
load(file.path(pfad, "etwas.RData"))
ls()
## [1] "pfad" "pfadu" "x" "y" "z"
Sollten wir nun tatsächlich x, y, und z wieder loswerden wollen, müssen wir diese allerdings löschen mit rm()
:
rm(list=c("x","y","z"))
ls()
## [1] "pfad" "pfadu"
Übrigens: sollten Sie alles in Ihrem workspace löschen wollen:
rm(list=ls())
All dies geht in RStudio unter Environment viel einfacher (wie oben erwähnt). Der Nachteil ist allerdings, dass Sie dieses Vorgehen in RStudio NICHT automatisieren können, während Sie die genannten Befehle nützen können, um diese in R-Skripte zu speichern, und auf diese Weise mehreren Usern, z.B. den Teilnehmern dieses Kurses, zukommen zu lassen. So werden wir z.B. in diesem Kurs sehr oft Dateien aus der Website pfadu
öffnen. Das geht mit read.table(file.path(pfadu,"Dateiname"))
viel schneller als wenn wir schreiben würden: “Öffnen Sie einen Browser und laden von folgender Website (dann folgt die Adresse) folgende Datei (deren Name dann folgt) herunter und speichern diese an einem Ort Ihrer Wahl. Öffnen Sie über Environment diese Datei.” usw. …
Außerdem brauchen Sie die oben genannten Befehle ohnehin, wenn Sie R
z.B. hier auf dem Server starten, um aufwendigere Berechnungen durchzuführen, die Ihren Laptop überlasten würden.
Wie wir gelernt haben, gibt es Funktionen in R. Diese schauen immer so aus:
x()
## Error in x(): konnte Funktion "x" nicht finden
Für viele Spezialanwendungen, die durch das “normale” R nicht abgedeckt sind gibt es ‘packages’, die Funktionen enthalten.
Nächste Stunde werden wir z.B. das package “ggplot2” kennenlernen. Dieses enthält u.a. die Funktion geom_boxplot()
, aber:
geom_boxplot()
## Error in geom_boxplot(): konnte Funktion "geom_boxplot" nicht finden
Wenn wir meinen, diese Funktion zu benötigen, müssen wir das package, das diese Funktion enthält, laden. Dazu müssen wir das package allerdings einmal installieren:
In RStudio:
Tools–>Install Packages
oder:
install.packages("ggplot2")
Das eigentliche Laden des packages geht über:
library(ggplot2)
geom_boxplot() #ist nun vorhanden
## geom_boxplot: outlier.colour = NULL, outlier.fill = NULL, outlier.shape = 19, outlier.size = 1.5, outlier.stroke = 0.5, outlier.alpha = NULL, notch = FALSE, notchwidth = 0.5, varwidth = FALSE, na.rm = FALSE
## stat_boxplot: na.rm = FALSE
## position_dodge2
Auch hier können wieder search()
und detach()
eingesetzt werden, um die Funktionen wieder aus dem Suchraum von R zu entfernen…
search()
## [1] ".GlobalEnv" "package:ggplot2" "package:stats"
## [4] "package:graphics" "package:grDevices" "package:utils"
## [7] "package:datasets" "package:methods" "Autoloads"
## [10] "package:base"
detach(2)
geom_boxplot()
## Error in geom_boxplot(): konnte Funktion "geom_boxplot" nicht finden
…und die Funktion (und alle anderen Funktionen aus ggplot2
) ist/sind wieder weg.
Für eine Einführung in R: ‘An Introduction to R’ in:
help.start()
Wenn Sie mehr über eine bestimmte Funktion wissen wollen, z.B. über pnorm()
:
help(pnorm)
# oder
?pnorm
example(density)
apropos("spline")
help.search("norm")
Allerdings: oftmals ist eine Suche über z.B. Google der schnellere und umfassendere Weg, da es so viele Benutzer von R und damit viele entsprechende Foren gibt.
Einen Überblick der vorhandene, allgemeingebräuchliche R-Funktionen bietet http://cran.r-project.org/doc/contrib/Short-refcard.pdf.
Ein Data-Frame ist eine Art Matrix mit verschiedenen Reihen und Spalten, die wir für die statistische Analyse sehr oft verwenden werden.
Die Data-Frames können so eingelesen werden (angenommen ‘0.02’ wurde durchgeführt):
ai.df = read.table(file.path(pfadu, "ai.txt"))
head(ai.df)
## F1 Kiefer Lippe
## 1 773 -25.47651 -24.59616
## 2 287 -27.02695 -26.44491
## 3 1006 -27.24509 -27.59161
## 4 814 -26.05803 -27.17365
## 5 814 -26.15489 -25.93095
## 6 806 -26.37281 -24.44872
vlax.df = read.table(file.path(pfadu, "vlax.txt"))
Durch die Klammer um den gesamten Befehl erzeugen Sie hier nicht nur vlax.df, sondern bekommen dessen Inhalt gleich angezeigt.
(vlax.df = read.table(file.path(pfadu, "vlax.txt")))
Sie speichern den Data-Frame als eine Text-Datei durch:
write.table(vlax.df, file.path(pfad, "v.txt"))
# besser: damit keine "" erscheinen
write.table(vlax.df, file.path(pfad, "v.txt"), quote=FALSE)
Oftmals werden wir die Notwendigkeit haben, uns einen data.frame selbt zusammenzubauen. Ein Beispiel hierfür ist:
# 10 Etikettierungen, 5 /i/, 5 /o/
v.l = c("i", "i", "i", "i", "i", "o", "o", "o", "o", "o")
# oder
v.l = c(rep("i", 5), rep("o", 5))
# oder
v.l = rep(c("i","o"),each=5)
f1 = c(240, 220, 250, 210, 280, 520, 510, 605, 670, 613)
vok.df = data.frame(f1, factor(v.l))
# mit anderen Namen
vok.df = data.frame(F1 = f1, V = v.l)
class(vok.df)
## [1] "data.frame"
summary(vok.df)
## F1 V
## Min. :210.0 i:5
## 1st Qu.:242.5 o:5
## Median :395.0
## Mean :411.8
## 3rd Qu.:583.8
## Max. :670.0
# Data-Frame ablegen und wieder einlesen
write.table(vok.df, file.path(pfad, "vok.txt"), quote=F)
read.table(file.path(pfad, "vok.txt"))
## F1 V
## 1 240 i
## 2 220 i
## 3 250 i
## 4 210 i
## 5 280 i
## 6 520 o
## 7 510 o
## 8 605 o
## 9 670 o
## 10 613 o
summary(vok.df)
## F1 V
## Min. :210.0 i:5
## 1st Qu.:242.5 o:5
## Median :395.0
## Mean :411.8
## 3rd Qu.:583.8
## Max. :670.0
class(vok.df$V)
## [1] "factor"
class(vok.df$F1)
## [1] "numeric"
with()
?with
#z.B.:
with(vok.df,F1)
## [1] 240 220 250 210 280 520 510 605 670 613
# =
vok.df$F1
## [1] 240 220 250 210 280 520 510 605 670 613
with(vok.df,table(V))
## V
## i o
## 5 5
# = (fast, zumindest...)
table(vok.df$V)
##
## i o
## 5 5
Mit ==
kann man fragen, ob zwei Dinge identisch sind; falls ja, wird TRUE
ausgegeben; das ==
ist also ganz was anderes als =
(Zuweisung; assign):
x = 0
y = 1
# x und y sind mit sich selbst natürlich identisch
x == x
## [1] TRUE
y == y
## [1] TRUE
x == y
## [1] FALSE
x == 0
## [1] TRUE
x == 1
## [1] FALSE
z = 0
x == z
## [1] TRUE
Eine Ausnahme: wenn wir wissen wollen ob "a"
ein Element von c("a","b","c")
, ist, brauchen wir %in%
anstelle von ==
:
"a" %in% c("a","b","c")
## [1] TRUE
Das alles kann man zur Auswahl anwenden:
vok.df$V
## [1] i i i i i o o o o o
## Levels: i o
vok.df$V == "i"
## [1] TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE
with(vok.df,V == "i")
## [1] TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE
Wenn man vok.df nur auf die Werte aus “i”-Vokalen beschränken will:
vok.df[vok.df$V == "i",]
## F1 V
## 1 240 i
## 2 220 i
## 3 250 i
## 4 210 i
## 5 280 i
# oder
vok.df[with(vok.df,V == "i"),]
## F1 V
## 1 240 i
## 2 220 i
## 3 250 i
## 4 210 i
## 5 280 i
Verbindung mehrerer logischer Vektoren mit logischem UND “&”:
# nur den "i"-Vokal mit F1 == 240
vok.df$V == "i" & vok.df$F1 == 240
## [1] TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
# =
with(vok.df,V =="i" & F1 == 240)
## [1] TRUE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
Wenn sich Ihnen jetzt noch nicht der Vorteil von with()
erschließen sollte: In späteren Sitzungen wird deutlicher werden, weshalb with()
so praktisch ist; vielleicht aber schon in den Antworten zu f1.R (diese Sitzung).
#Nun den logischen Vektor in den data.frame stecken, um diesen zu filtern:
#alles, wo in dem parallelen log. Vektor TRUE ist, wird ausgewählt:
vok.df[vok.df$V == "i" & vok.df$F1 == 240,]
## F1 V
## 1 240 i
#oder
vok.df[with(vok.df,V =="i" & F1 == 240),]
## F1 V
## 1 240 i
Die library(dplyr) macht das aber viel, viel einfacher; sie verwendet aber auch logische Vektoren:
install.packages("dplyr")
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
#... und zwar wird es einfacher durch den filter()-Befehl:
filter(vok.df,V=="i" & F1==240)
## F1 V
## 1 240 i
#... oder z.B.
filter(ai.df,F1==1005)
## F1 Kiefer Lippe
## 1 1005 -27.98772 -28.26871
filter()
ist eines der sogenannten “Verben” in dplyr
. Es gibt nur eine begrenzte Anzahl: filter()
, arrange()
, select()
, rename()
, mutate()
,transmute()
,summarise()
,sample_n()
,sample_fraq()
Heute besprechen wir nur das sehr nützliche “Verb” filter()
, sowie select()
:
select(ai.df,1)
## F1
## 1 773
## 2 287
## 3 1006
## 4 814
## 5 814
## 6 806
## 7 938
## 8 1005
## 9 964
## 10 931
## 11 926
## 12 556
## 13 707
## 14 829
## 15 927
## 16 951
## 17 775
## 18 938
## 19 986
## 20 888
## 21 988
## 22 650
## 23 1026
## 24 992
## 25 896
select(ai.df,F1)
## F1
## 1 773
## 2 287
## 3 1006
## 4 814
## 5 814
## 6 806
## 7 938
## 8 1005
## 9 964
## 10 931
## 11 926
## 12 556
## 13 707
## 14 829
## 15 927
## 16 951
## 17 775
## 18 938
## 19 986
## 20 888
## 21 988
## 22 650
## 23 1026
## 24 992
## 25 896
#das Gegenteil, also der Rest des data.frames
select(ai.df,-F1)
## Kiefer Lippe
## 1 -25.47651 -24.59616
## 2 -27.02695 -26.44491
## 3 -27.24509 -27.59161
## 4 -26.05803 -27.17365
## 5 -26.15489 -25.93095
## 6 -26.37281 -24.44872
## 7 -27.35341 -27.22650
## 8 -27.98772 -28.26871
## 9 -26.27536 -27.05215
## 10 -26.09928 -26.54016
## 11 -26.40012 -26.83834
## 12 -25.73544 -27.21908
## 13 -25.84109 -23.44627
## 14 -26.37598 -25.23304
## 15 -27.47505 -27.64328
## 16 -26.68685 -25.63057
## 17 -25.79928 -23.68594
## 18 -27.18105 -25.28667
## 19 -27.75178 -27.70719
## 20 -25.99100 -26.84534
## 21 -26.27380 -28.26909
## 22 -26.50057 -24.31192
## 23 -27.10303 -24.64248
## 24 -28.41081 -28.30641
## 25 -26.57372 -25.69383
select()
greift also auf Spalten zu.
Gibt es auch einen Befehl, um spezifische Zeilen anzeigen zu lassen?
Natürlich! Aber: Der slice()
-Befehl wird nicht zu den Basisverben von dplyr
gerechnet. Dieser Befehl gibt die Zeile(n) aus, die man angibt, z.B.:
slice(ai.df,5:7)
## F1 Kiefer Lippe
## 1 814 -26.15489 -25.93095
## 2 806 -26.37281 -24.44872
## 3 938 -27.35341 -27.22650
Aber: Wie man sieht: das Ausgabeformat ist kein data.frame
mehr, sondern ein sogenanntes tibble
. Doch dazu später mehr…