Wie Ausgabe in R funktioniert
R hat eine Angewohnheit, die keine andere verbreitete Sprache teilt: An der Konsole brauchst du überhaupt keine Print-Anweisung. Tipp den Namen einer Variablen, drück Enter, und R gibt ihren Wert aus. Das ist Auto-Printing, und deshalb sind R-Tutorials voller nackter Ausdrücke.
Aber Auto-Printing hat eine strikte Grenze: Es greift nur bei Ausdrücken auf oberster Ebene. In einer for-Schleife oder einem Funktionsrumpf wird ein nackter Wert ausgewertet und stillschweigend weggeworfen:
Das einsame x wird ausgegeben (es steht auf oberster Ebene), die erste Schleife gibt gar nichts aus, und die zweite gibt 1, 2, 3 aus, weil sie es explizit verlangt. "Meine Schleife läuft, zeigt aber nichts" ist eine der meistgestellten R-Fragen, und das ist die ganze Antwort: In Schleifen und Funktionen ist Ausgabe immer deine Aufgabe. (Dasselbe gilt, wenn du ein Skript mit Rscript ausführst - was zeilenweise an der Konsole funktionierte, kann in einer Schleife verstummen.)
print(): der Förmliche
print() zeigt einen Wert so, wie R ihn sieht - was es zum richtigen Werkzeug zum Inspizieren von Daten macht und zum falschen für polierte Ausgaben:
Zwei Dinge fallen auf. Zeichenketten behalten ihre Anführungszeichen - print() zeigt dir eine getreue Darstellung, und die Anführungszeichen sagen dir, dass es ein Zeichenwert ist. Und jede Zeile beginnt mit einer eingeklammerten Zahl wie [1]: Das ist der Index des ersten Elements in dieser Zeile, sodass bei einem langen, umgebrochenen Vektor jede Klammer verrät, bei welchem Element die Zeile fortsetzt. Es ist eine Lesehilfe für Vektoren, kein Rauschen.
Willst du print()-Ausgabe ohne die Anführungszeichen, tun das sowohl print(x, quote = FALSE) als auch noquote(x) - meist ist das, was du an dieser Stelle eigentlich willst, aber cat().
cat(): Ausgabe für Menschen
cat() (concatenate-and-print) schreibt rohen Text: keine Anführungszeichen, keine Indexpräfixe, und die Argumente mit Leerzeichen verbunden. Der Preis dieser Kontrolle ist, dass nichts für dich hinzugefügt wird - auch nicht der Zeilenumbruch:
Das "\n" zu vergessen ist der universelle cat()-Initiationsritus - ohne es klebt die nächste Ausgabe an derselben Zeile. Mach es dir zum Reflex, cat()-Aufrufe mit "\n" zu beenden.
Der Anführungszeichen-Unterschied zwischen beiden Funktionen ist in Wahrheit ein Unterschied darin, was sie zeigen. print() stellt Escape-Sequenzen so dar, wie du sie getippt hast; cat() rendert sie:
print() zeigt \t und \n wörtlich in Anführungszeichen - nützlich, wenn du debuggst, was genau eine Zeichenkette enthält. cat() macht daraus einen echten Tabulator und einen echten Zeilenumbruch - nützlich, wenn du Ausgabe erzeugst. Wähle nach Absicht: print() zum Inspizieren, cat() zum Präsentieren.
Formatierte Berichte: sprintf() + cat()
Die leerzeichengetrennten Argumente von cat() kommen nur so weit. Für ausgerichtete, formatierte Ausgabe - feste Nachkommastellen, aufgefüllte Zähler - baust du die Zeichenkette mit sprintf() und übergibst sie an cat():
%-8s füllt jeden Namen auf 8 Zeichen auf und %6.2f gibt jeder Punktzahl dieselbe Breite und zwei Nachkommastellen, sodass die Spalten fluchten. Dieses Paar ist das Base-R-Arbeitspferd für Fortschrittsmeldungen und kleine Textberichte (die Formatcodes werden unter Zeichenketten behandelt).
message() und warning(): der andere Kanal
cat() und print() schreiben auf die Standardausgabe - den Strom, der die Ergebnisse deines Programms enthält. message() und warning() schreiben auf die Standardfehlerausgabe, den Strom für Kommentare zum Lauf:
Auf dem Bildschirm sehen beide ähnlich aus, aber die Trennung zählt in dem Moment, in dem die Ausgabe umgeleitet wird: Leitest du stdout deines Skripts in eine Datei, landet die 42 in der Datei, während die Statusnotiz im Terminal bleibt. Das ist die Faustregel - Ergebnisse auf stdout mit cat(), Kommentare auf stderr mit message(). Deshalb ist message() (nicht cat()) auch der höfliche Weg für Funktionen und Pakete, mit ihren Nutzern zu sprechen: Aufrufer können es mit suppressMessages() stumm schalten, ohne echte Ausgabe zu verlieren.
warning() ist stärker - "etwas stimmt nicht, aber ich habe weitergemacht" - und wenn ein Skript unter Rscript läuft, werden Warnungen gesammelt und am Ende gemeinsam gezeigt statt an Ort und Stelle (siehe Fehler debuggen zum Lesen dieser Meldungen).
Benutzereingaben lesen: readline() und readLines()
Um dem Nutzer in einer interaktiven Sitzung (der R-Konsole oder RStudio) eine Frage zu stellen, nutze readline(). Diese Beispiele sind im eingebetteten Editor nicht ausführbar - der Runner auf der Seite hat kein Eingabefeld -, probier sie also in einer lokalen Konsole:
# Interactive sessions only:
name <- readline("What is your name? ")
cat("Hello,", name, "\n")
age <- as.numeric(readline("Your age? "))
cat("Next year you'll be", age + 1, "\n")
Zwei Dinge zum Merken. readline() gibt immer eine Zeichenkette zurück - konvertiere mit as.numeric(), bevor du rechnest, und prüfe das Ergebnis auf NA, falls der Nutzer etwas eingetippt hat, das keine Zahl ist. Und in einem nicht-interaktiven Skript wartet readline() überhaupt nicht auf Eingabe; es gibt sofort "" zurück.
Für ein mit Rscript ausgeführtes Skript, das gepipte oder getippte Eingaben lesen soll, lies stattdessen von der Standardeingabe:
# In a script run as: echo "Ada" | Rscript greet.R
line <- readLines(con = "stdin", n = 1)
cat("Hello,", line, "\n")
readLines(con = "stdin") ohne n liest jede Zeile, bis die Eingabe endet - die Standardform für Filter-Skripte. Das Lesen von Datendateien ist eine andere Aufgabe mit besseren Werkzeugen; beginne mit read-csv, wenn deine Eingabe ein Datensatz statt einer Tastatur ist.
Was du mitnimmst
- Auto-Printing passiert nur auf oberster Ebene - in Schleifen und Funktionen rufst du
print()odercat()selbst auf. print()inspiziert: Anführungszeichen bei Zeichenketten,[1]-Indexpräfixe, Escapes wörtlich dargestellt.cat()präsentiert: roher Text, Argumente durch Leerzeichen verbunden, und du lieferst das"\n".sprintf()+cat()ist das Base-R-Muster für formatierte, ausgerichtete Ausgabe.- Ergebnisse gehen auf stdout (
cat), Kommentare auf stderr (message,warning). readline()für interaktive Eingaben (immer eine Zeichenkette!);readLines(con = "stdin")für Rscript.
Als Nächstes: Operatoren - Arithmetik, Vergleiche und die logischen Operatoren, die jede Bedingung antreiben, die du schreiben wirst.
Häufig gestellte Fragen
Was ist der Unterschied zwischen print() und cat() in R?
print() zeigt einen Wert so, wie R ihn darstellt - Zeichenketten behalten ihre Anführungszeichen und jede Zeile bekommt ein Indexpräfix im [1]-Stil. cat() schreibt rohen Text ohne Anführungszeichen, ohne Indizes und ohne automatischen Zeilenumbruch ("\n" fügst du selbst hinzu). Nutze print() zum Inspizieren von Objekten und cat() für Ausgaben an Menschen.
Warum gibt meine R-Schleife nichts aus?
Auto-Printing passiert nur bei Ausdrücken auf oberster Ebene. In einer for-Schleife oder einem Funktionsrumpf wird ein nacktes x ausgewertet und stillschweigend verworfen. Schreib es explizit: print(x) oder cat(x, "\n").
Wie liest man in R Benutzereingaben ein?
In einer interaktiven Sitzung liest readline("prompt: ") eine getippte Eingabezeile als Zeichenkette (mit as.numeric() konvertieren, wenn du eine Zahl brauchst). In einem mit Rscript ausgeführten Skript wartet readline() nicht - lies stattdessen von der Standardeingabe mit readLines(con = "stdin", n = 1).
Wie gibt man in R ohne Anführungszeichen aus?
Nutze cat("hello\n") - es setzt nie Anführungszeichen. Wenn du gezielt print()-Semantik ohne Anführungszeichen willst, funktionieren auch print("hello", quote = FALSE) oder noquote("hello").