Textverarbeitung mit R: Mit format() verwandte Funktionen

Die Funktion format.info() liefert Informationen über den Rückgabewert von format(). Die Funktion formatC() bildet eine Alternative zu format() und mit ihr werden Formatierungsanweisungen ähnlich wie in der Programmiersprache C formuliert. Die Funktion prettyNum() wird von formatC() intern genutzt, um Zahlen zu formatieren.

Einordnung des Artikels

Einführung

Besprochen werden hier 3 Funktionen, die mit format() verwandt sind; diese wurde in Textverarbeitung mit R: Die Funktion format() zum Formatieren von Objekten für Ausgaben ausführlich besprochen und Kenntnisse über ihre Eigenschaften werden hier vorausgesetzt. Im Folgenden werden erläutert:

  1. format.info()
  2. formatC() und
  3. prettyNum().

Abbildung 1 versucht diese Funktionen und ihren Zusammenhang mit format() zu erklären.

Etwas ausführlicher:

  1. Die Funktion format.info() dient nicht zum Formatieren von Objekten. Wird sie mit den Eingabewerten aufgerufen, die an format() übergeben werden, erhält man als Rückgabewert einen Vektor, der die von format() erzeugte Ausgabe beschreibt, nämlich die Feldbreite der formatierten Zahl, die Anzahl der Stellen nach dem Komma sowie die Anzahl der Stellen (verringert um 1) für den Exponenten in wissenschaftlicher Darstellung.
  2. Die Funktion formatC() wird als Alternative zu format() angeboten. Ihre Eingabewerte und ihr Verhalten stimmen weitgehend mit den Formatierungsanweisungen überein, wie sie in der Programmiersprache C formuliert werden; wer damit vertraut ist, wird sich leicht einarbeiten können. Einige kleine Unterschiede bestehen zu format(), die insbesondere die Verarbeitung von Vektoren betreffen.
  3. Die Funktion prettyNum() wird sowohl von format() als auch von formatC() intern verwendet. Die Formatierung von Zahlen mit formatC() wird vollständig von prettyNum() übernommen. Daher ist es nach der ausführlichen Darstellung der Eigenschaften von formatC() nicht mehr nötig die Funktion prettyNum() zu erklären.

Abbildung 1: Versuch einer graphischen Darstellung der hier besprochenen Funktionen ''format()'', formatC(), ''format.info()'' und ''prettyNum()''. Die Funktion ''prettyNum()'' wird intern von ''format()'' und ''formatC()'' genutzt. Die Funktion ''format.info()'' liefert Aussagen über den von ''format()'' erzeugten Rückgabewert.Abbildung 1: Versuch einer graphischen Darstellung der hier besprochenen Funktionen ''format()'', formatC(), ''format.info()'' und ''prettyNum()''. Die Funktion ''prettyNum()'' wird intern von ''format()'' und ''formatC()'' genutzt. Die Funktion ''format.info()'' liefert Aussagen über den von ''format()'' erzeugten Rückgabewert.

Die Funktion format.info()

Die Funktion format.info() liefert Informationen darüber, welche Eigenschaften die von format() erzeugten Zeichenketten haben. Mit "Eigenschaften" ist hier gemeint, dass ein Vektor mit drei Komponenten erzeugt wird, die folgende Bedeutung haben:

  1. Die gesamte Feldbreite der dargestellten Zahl.
  2. Die Anzahl der Stellen nach dem Komma.
  3. Der Exponent in wissenschaftlicher Darstellung kann Werte zwischen -308 und +308 annehmen, kann also in der Ausgabe 1, 2 oder 3 Stellen beanspruchen. Diese Anzahl verringert um 1 wird als dritte Komponente angegeben.

Wird nicht nur eine einzige Zahl sondern ein Vektor x verarbeitet, müssen diese drei Werte für jede Komponente von x übereinstimmen. Die Implementierung von format() sorgt für dieses Verhalten – bei der Diskussion von formatC() wird sich zeigen, dass ihr Verhalten davon abweichen kann.

Um format.info() aufzurufen, werden einfach die Formatierungsanweisungen, die an format() gegeben wurden, an format.info() übergeben. Der Rückgabewert ist dann der oben beschriebene Vektor mit drei Komponenten.

Beispiele:

Im ersten Beispiel (siehe Zeile 1 bis 66) werden die Vielfachen der Kreiszahl π berechnet und mit format(pi, digits = i, nsmall = 4) ausgegeben (Zeile 3); zusätzlich werden diese Eingabewerte am format.info() übergeben (Zeile 4).

Im zweiten Beispiel wird die wissenschaftliche Schreibweise untersucht (Zeile 68 bis 71).

for(i in (1:20)){
  cat("digits = ", i, ":\n")
  print(format(pi, digits = i, nsmall = 4))
  print( format.info(pi, digits = i, nsmall = 4) )
}

# digits =  1 :
#   [1] "3.1416"
# [1] 6 4 0
# digits =  2 :
#   [1] "3.1416"
# [1] 6 4 0
# digits =  3 :
#   [1] "3.1416"
# [1] 6 4 0
# digits =  4 :
#   [1] "3.1416"
# [1] 6 4 0
# digits =  5 :
#   [1] "3.1416"
# [1] 6 4 0
# digits =  6 :
#   [1] "3.14159"
# [1] 7 5 0
# digits =  7 :
#   [1] "3.141593"
# [1] 8 6 0
# digits =  8 :
#   [1] "3.1415927"
# [1] 9 7 0
# digits =  9 :
#   [1] "3.14159265"
# [1] 10  8  0
# digits =  10 :
#   [1] "3.141592654"
# [1] 11  9  0
# digits =  11 :
#   [1] "3.1415926536"
# [1] 12 10  0
# digits =  12 :
#   [1] "3.14159265359"
# [1] 13 11  0
# digits =  13 :
#   [1] "3.14159265359"
# [1] 13 11  0
# digits =  14 :
#   [1] "3.1415926535898"
# [1] 15 13  0
# digits =  15 :
#   [1] "3.14159265358979"
# [1] 16 14  0
# digits =  16 :
#   [1] "3.141592653589793"
# [1] 17 15  0
# digits =  17 :
#   [1] "3.1415926535897931"
# [1] 18 16  0
# digits =  18 :
#   [1] "3.1415926535897931"
# [1] 18 16  0
# digits =  19 :
#   [1] "3.1415926535897931"
# [1] 18 16  0
# digits =  20 :
#   [1] "3.1415926535897931"
# [1] 18 16  0

format(6.023e23, digits = 3)
# "6.02e+23"
format.info(6.023e23, digits = 3)
# 8 2 1

Zeile 1 bis 6: Ausgabe der Kreiszahl π mit unterschiedlicher Anzahl an gültigen Stellen sowie die zugehörige Ausgabe von format.info().

Zeile 68 bis 71: Die Ausgabe beansprucht insgesamt 8 Stellen, nach dem Komma werden 2 Stellen angezeigt und der Exponent hat 1 + 1 = 2 Stellen.

Die Funktion formatC()

In Textverarbeitung mit R: Die Funktion format() zum Formatieren von Objekten für Ausgaben wurde besprochen, welche Funktionalitäten format() anbietet. Die Funktion formatC() versucht identische Funktionalitäten bereitzustellen, wobei einige Eingabewerte abgewandelt werden; der Buchstabe C in formatC() deutet darauf hin, dass es hier dem Programmierer ermöglicht werden soll, die Befehle sehr ähnlich wie in der Programmiersprache C zu formulieren. Wer also mit C vertraut ist, wird die Funktion formatC() gegenüber format() bevorzugen.

Es werden nicht alle Eingabewerte besprochen – die Liste aller Eingabewerte ist dem folgenden Skript zu entnehmen:

formatC(x, digits = NULL, width = NULL,
        format = NULL, flag = "", mode = NULL,
        big.mark = "", big.interval = 3L,
        small.mark = "", small.interval = 5L,
        decimal.mark = getOption("OutDec"),
        preserve.width = "individual",
        zero.print = NULL, replace.zero = TRUE,
        drop0trailing = FALSE)

Der Eingabewert x und der Rückgabewert

Üblicherweise steht der Eingabewert x für eine Zahl, die für die Ausgabe geeignet dargestellt werden soll. Es kann aber auch ein Vektor eingegeben werden; die Formatierungsanweisung wird dann an die einzelnen Komponenten weitergegeben.

Das folgende Skript zeigt zwei einfache Beispiele:

formatC(x = pi)
# "3.142"

formatC(x = (1:4) * pi)
# "3.142" "6.283" "9.425" "12.57"

Zeile 1 und 2: Die Kreiszahl π wird an formatC() übergeben, wobei keine Formatierungsanweisungen gegeben werden. Man erkennt, dass per default vier gültige Stellen ausgegeben werden.

Zeile 4 und 5: Vielfache der Kreiszahl π werden ausgegeben. Man erkennt, dass der Vektor problemlos verarbeitet werden kann. Die Formatierungsanweisung wird an jede einzelne Komponente weitergereicht. Dadurch wird jede Komponente mit 4 gültigen Stellen angegeben. Denkbar wäre auch, dass die Anzahl der Nachkommastellen für alle Komponenten identisch ist – dies ist bei formatC() nicht der Fall.

Aufgabe: Vergleichen Sie die letzte Anweisung (Zeile 4) mit format(x = (1:4) * pi) und format(x = (1:4) * pi, digits = 4) . Beschreiben Sie die Unterschiede.

♦ ♦ ♦

Der Eingabewert kann auch eine Zeichenkette (oder ein Vektor von Zeichenketten) sein – jetzt erfolgt die Ausgabe aber nicht mit den vier gültigen Stellen wie bei Zahlen:

formatC(x = as.character(4 * pi))
# "12.5663706143592"

Wie an den auskommentierten Ergebnissen jeweils zu sehen war (Anführungsstriche!), ist der Rückgabewert von formatC() vom Modus character; das folgende Beispiel zeigt es ausdrücklich:

str(formatC(x = (1:4) * pi))
# chr [1:4] "3.142" "6.283" "9.425" "12.57"

Für formatC() gilt somit auch die Warnung, die bei format() ausgesprochen wurde:

Die Funktion formatC() soll nur eingesetzt werden, um Zahlen für die Ausgabe geeignet darzustellen. Möchte man mit den gerundeten Zahlen weiter rechnen, wird man andere Funktionen einsetzen, die tatsächlich Zahlen als Rückgabewert besitzen.

Das Argument digits

Wie bei der Funktion format() spielt das Argument digits eine zentrale Rolle, da mit ihm die Anzahl der Nachkommastellen beziehungsweise der gültigen Stellen einer Zahl festgelegt wird. In der Funktion formatC() hängt die Wirkung von digits allerdings ab, wie das Argument format gesetzt ist; insbesondere wenn format = "fg" gesetzt wird (Genaueres siehe unten). Daher werden beide Argumente format und digits im nächsten Unterabschnitt gemeinsam besprochen.

Die Argumente format und digits

Übersicht

Das Argument format kann einen der Werte

Die folgende Tabelle beschreibt kurz ihre Bedeutung, in den Skripten darunter werden einfache Beispiele gezeigt:

d bewirkt die Darstellung als ganze Zahl
f bewirkt die Darstellung als Gleitkommazahl
e Exponentialdarstellung mit kleinem e
E Exponentialdarstellung mit großem E
g Es wird die Version aus format = "f" und format = "e" gewählt, die zu einer kürzeren Darstellung führt.
G Es wird die Version aus format = "f" und format = "E" gewählt, die zu einer kürzeren Darstellung führt.
fg Wie format = "f" , aber zusätzlich wird der Wert von digits verwendet, der die Mindestanzahl an signifikanten Stellen angibt.
s für Zeichenketten

Beispiele mit ganzen Zahlen

Das folgende Skript zeigt die wichtigsten Befehle, die man kennen sollte, um ganze Zahlen darzustellen:

n <- 10000L
m <- 10000

formatC(x = n)
# "10000"

formatC(x = pi, format = "d")
# "3"

formatC(x = m)
# "1e+04"

formatC(n, digits = 7)
# "   10000"

Zeile 1 und 2: Es werden zwei Variablen vom Speichermodus integer beziehungsweise double initialisiert

Zeile 4 und 5: Für Zahlen vom Speichermodus integer ist der default-Wert von format gleich "d" , es muss daher nicht angegeben werden und man erhält die übliche Ausgabe einer ganzen Zahl.

Zeile 7 und 8: Wird eine Zahl mit Nachkommastellen, hier die Kreiszahl π mit format = "d" ausgegeben, so wird sie abgeschnitten, um eine ganze Zahl zu erhalten.

Zeile 10 und 11: Die Variable m hat Speichermodus double. Aufgrund des default-Wertes format = "g" wird m in wissenschaftlicher Schreibweise ausgegeben.

Zeile 13 und 14: Hier hat digits nicht die Wirkung, die man vielleicht erwartet; es werden keine Nachkommastellen angehängt, um die 7 gültigen Stellen zu erreichen. Stattdessen wird die Breite des Feldes vergrößert, das den Zahlenwert aufnimmt. Die Feldbreite, die eigentlich durch das Argument width festgelegt wird, beträgt hier 8 Zeichen. Im Unterabschnitt zu width wird erklärt, dass der default-Wert von width = digits + 1 ist. Daher wird hier die Zahl n wie üblich als natürliche Zahl ausgegeben, aber in ein Feld der Breite 8 geschrieben.

Beispiele mit Gleitkommazahlen

Das folgende Skript zeigt die wichtigsten Befehle, die man kennen muss, um Fließkommazahlen darzustellen:

n <- 10000L

formatC(n, format = "f")
# "10000.0000"

formatC(pi, format = "g")
# "3.142"

formatC(n * pi, format = "g")
# "3.142e+04"

formatC(n * pi, format = "f")
# "31415.9265"

formatC(n * pi, format = "d")
# "31415"

formatC(n * pi, format = "f", digits = 7)
# "31415.9265359"

formatC(n * pi, format = "fg")
# "31416"

formatC(n * pi, format = "fg", digits = 8)
# "31415.927"

formatC(n * pi, format = "e")
# "3.1416e+04"
formatC(n * pi, format = "E")
# "3.1416E+04"
formatC(n * pi, format = "e", digits = 2)
# "3.14e+04"

Zeile 1: Die Variable n hat wieder Speichermodus integer.

Zeile 3 und 4: Durch die Formatierungsanweisung format = "f" wird die Variable n wie eine Fließkommazahl behandelt und (per default) mit 4 Nachkommastellen ausgegeben.

Zeile 6 und 7: Mit format = "g" wird zuerst geprüft, ob die übliche Darstellung als Fließkommazahl oder die wissenschaftliche Darstellung kürzer ist. Zur Darstellung der Kreiszahl π wird die übliche Darstellung als Fließkommazahl mit 4 gültigen Stellen (default) ausgewählt.

Zeile 8 und 9: Bildet man dagegen 10000·π, so ist die wissenschaftliche Darstellung kürzer (Ausgabe wieder mit 4 gültigen Stellen).

Zeile 12 bis 16: Wird 10000·π mit format = "f" beziehungsweise format = "d" ausgegeben, erfolgt die Ausgabe mit 4 Nachkommastellen beziehungsweise die Nachkommastellen werden abgeschnitten.

Zeile 18 und 19: Setzt man format = "f" , so kann man mit digits die Anzahl der Nachkommastellen geeignet anpassen.

Zeile 21 bis 25: Verwendet man format = "fg" , so wird digits als die Mindestanzahl an gültigen Stellen eingesetzt. Da der default-Wert für digits gleich 4 ist, werden bei formatC(n * pi, format = "fg") die 5 Stellen vor dem Komma angezeigt, da 4 gültige Stellen nicht ausreichen, um die Zahl anzuzeigen. (Man vergleiche Zeile 21 und 22 mit Zeile 18 und 19.)

Dagegen werden bei formatC(n * pi, format = "fg", digits = 8) tatsächlich die geforderten 8 Stellen ausgegeben.

Zeile 27 bis 32: Beispiele für die Verwendung der wissenschaftlichen Schreibweise.

Beispiele mit Zeichenketten

Bei Zahlen, die bereits in Zeichenketten umgewandelt wurden, sorgt format = "s" dafür, dass die Zeichenketten einfach so ausgegeben werden wie sie an x übergeben wurden. Dabei wird nicht geprüft, ob die Zeichen tatsächlich einer Zahl entsprechen (siehe Zeile 1, 4 und 7). Diese "Zahlen" aus Zeichen können nicht mehr wie übliche Zahlen behandelt werden (siehe Zeile 10).

formatC(as.character(n * pi), format = "s")
# "31415.9265358979"

formatC("000", format = "s")
# "000"

formatC("xyz", format = "s")
# "xyz"

formatC("3.14159", format = "s", digits = 7)
# "3.14159"

Das Argument width

Das Argument width gibt die Feldbreite an, in die eine Zahl geschrieben wird. Das folgende Skript zeigt typische Beispiele:

v <- 10^(1:3)
v
# [1]   10  100 1000

formatC(x = v, width = 5)
# "   10" "  100" " 1000"

formatC(x = v, digits = 2, width = 6)
# "    10" " 1e+02" " 1e+03"

formatC(x = 1 / v)
# "0.1"   "0.01"  "0.001"

formatC(x = 1 / v, digits = 3)
# " 0.1"  "0.01"  "0.001"

formatC(x = 1 / v, width = 5)
# "  0.1" " 0.01" "0.001"

Zeile 1 bis 3: Die Zahlen 10, 100 und 1000 werden zu einem Vektor v zusammengefasst.

Zeile 5 und 6: Setzt man zur Ausgabe von v die Feldbreite width = 5 , so wird jede Komponente des Vektors in ein Feld der Breite 5 geschrieben; dies kann wichtig sein, wenn etwa ein "Flattern" von Tabellen vermieden werden soll.

Zeile 8 und 9: Setzt man digits = 2 , so muss die wissenschaftliche Schreibweise verwendet werden. Die Ausgabe einer Zahl wie 1e+03 benötigt 5 Zeichen; daher wird bei digits = 6 zusätzlich ein führendes Leerzeichen ausgegeben.

Zeile 11 und 12: Die Kehrwerte der Komponenten von v werden ausgegeben ohne weitere Argumente zu setzen. Jetzt variiert die Breite des Feldes, in die die Komponenten geschrieben werden.

Zeile 14 bis 18: Es besteht ein subtiler Unterschied ob man das Argument digits oder das Argument width einsetzt, den man nur verstehen kann, wenn man den default-Wert von width kennt: Sobald digits gesetzt ist, ist der default-Wert von width gleich digits + 1 .

Bei der Verwendung von digits = 3 werden die Kehrwerte nahezu identisch zum Befehl formatC(x = 1 / v) ausgegeben, da unnötige Nullen nicht dargestellt werden. Allerdings (man vergleiche mit Zeile 15 und Zeile 12!) wird jetzt jede Komponente in ein Feld der Breite 4 geschrieben.

Wird nur digits gesetzt (in Zeile 14), werden die identisch dargestellten Zahlen in das Feld der Breite width gesetzt (mit width = digits + 1) . Man beachte daher, dass mit digits zugleich das Argument width gesetzt wird.

Das Argument flag

Zuletzt wurde gezeigt, wie das Argument width eingesetzt werden kann, um eine feste Breite des Feldes festzulegen, in das Zahlen geschrieben werden, die ansonsten eine unterschiedliche Feldbreite beanspruchen würden. Oftmals führt auch ein Vorzeichen zu einem "Flattern" der Ausgabe, da per default immer nur das Minuszeichen angezeigt wird. Eine andere Ursache für "Flattern" liegt in der unterschiedlichen Anzahl der gültigen Stellen der Komponenten eines Vektors. Hier bietet das Argument flag weitere Möglichkeiten der Formatierung – die wichtigsten werden im folgenden Skript gezeigt:

v <- 10^(1:3)
v
# [1]   10  100 1000

w <- c(0, 1, -2, 3, -4)
w
# [1]  0  1 -2  3 -4

formatC(x = 1 / v, flag = "0", width = 5)
# "000.1" "00.01" "0.001"

formatC(x = 1 / v, flag = "-", width = 5)
# "0.1  " "0.01 " "0.001"

formatC(x = w, flag = "+")
# "+0" "+1" "-2" "+3" "-4"

formatC(x = w, flag = " ")
# " 0" " 1" "-2" " 3" "-4"

formatC(x = 1 / v, format = "g")
# "0.1"   "0.01"  "0.001"

formatC(x = 1 / v, format = "g", flag = "#")
# "0.1000"   "0.01000"  "0.001000"

formatC(x = 1 / v, format = "g", flag = "#", digits = 5)
# "0.10000"   "0.010000"  "0.0010000"

Zeile 1 bis 7: Definition der Vektoren v und w, die in den folgenden Beispielen verwendet werden.

Zeile 9 und 10: Werden die Kehrwerte von v ausgegeben, so entstehen per default Zahlen unterschiedlicher Länge. Mit flag = "0" werden führende Nullen erzeugt, um die durch width festgelegte Feldbreite zu erzielen.

Zeile 12 und 13: Die Kehrwerte von v werden in ein Feld der Breite width = 5 ; das Argument flag = "-" sorgt dafür, dass die Felder linksbündig gefüllt werden (Leerzeichen werden rechts eingesetzt, um das Feld zu füllen).

Zeile 15 und 16: Das Argument flag = "+" bewirkt, dass bei positiven Zahlen und der 0 ein Pluszeichen angezeigt wird.

Zeile 18 bis 19: Mit flag = " " werden die Pluszeichen wieder unterdrückt, aber stattdessen wird ein Leerzeichen vor die positiven Zahlen (und die 0) gesetzt.

Zeile 21 bis 28: Üblicherweise wird eine Zahl wie 0.010 als 0.1 dargestellt und die 0 rechts abgeschnitten (obwohl sie oft benötigt wird, um die Genauigkeit der Angabe zu zeigen), siehe zum Beispiel Zeile 21. Mit Hilfe von flag = "#" kann jetzt die Angabe der Nullen rechts erzwungen werden (per default werden die Zahlen mit 4 signifikanten Stellen ausgegeben, siehe Zeile 24 und 25). Die Anzahl der Nullen rechts, genauer die Anzahl der signifikanten Stellen, kann mit dem Argument digits festgelegt werden, siehe Zeile 27 und 28. Jetzt besitzen die Komponenten des Vektors keine gemeinsame Feldbreite sondern die identische Anzahl an gültigen Stellen (im Beispiel Zeile 28 nämlich 5 gültige Stellen).

Die Argumente big.mark, big.interval, small.mark, small.interval und decimal.mark

Sollen die Zahlenwerte von sehr großen Zahlen leicht lesbar dargestellt werden – etwa bei der Angabe von Geldbeträgen –, bevorzugt man anstelle einer Darstellung wie 1000000 oft eine Trennung in Dreiergruppen, hier also 1.000.000. Sowohl das Trennungszeichen (im Beispiel . ) als auch die Länge der Untergruppen (hier 3 ) kann festgelegt werden; dazu dienen die Argumente big.mark und big.interval (der Name big soll daran erinnern, dass es sich um die Stellen vor dem Komma handelt, mit small werden dann die Nachkommastellen angesprochen).

Man muss dabei aber darauf achten, dass als Trennungszeichen nicht das Zeichen für den Dezimalpunkt verwendet wird. Über das Argument decimal.mark kann dessen Zeichen festgelegt werden.

Auch die Nachkommastellen einer Gleitkommazahl können mit einem selbst definierten Trennungszeichen gruppiert werden; die entsprechende Länge der Untergruppen wird mit small.interval und das Trennungszeichen mit small.mark definiert.

Das folgende Skript zeigt den Einsatz dieser Argumente:

formatC(x = 1000000.1234567, format = "f", digits = 7)
# "1000000.1234567"

formatC(x = 1000000.1234567, format = "f", digits = 7, big.mark = ".", decimal.mark = ",")
# "1.000.000,1234567"

formatC(x = 1000000.1234567, format = "f", digits = 7, 
        big.mark = ".", decimal.mark = ",", small.mark = "_")
# "1.000.000,12345_67"

formatC(x = 1000000.1234567, format = "f", digits = 7, 
        big.mark = ".", decimal.mark = ",", big.interval = 2,
        small.mark = "_", small.interval = 2)
# "1.00.00.00,12_34_56_7"

Zeile 1 und 2: Die Zahl 1000000.1234567 wird mit format = "f" und ihren 7 Nachkommastellen (durch digits = 7 ) ausgegeben – ohne Trennungszeichen sind die Stellen vor dem Komma schwer lesbar.

Zeile 4 und 5: Die Stellen vor dem Komma sollen in Dreiergruppen dargestellt werden; dazu ist keine Anweisung nötig, da der default-Wert von big.interval natürlich 3 beträgt. Mit big.mark = "." wird das Trennungszeichen zwischen den Dreiergruppen festgelegt. Da der Punkt . als Dezimalpunkt verwendet wird, muss das Zeichen für den Dezimalpunkt neu definiert werden; dies geschieht hier mit decimal.mark = "," .

Zeile 7 bis 9: Zusätzlich können die Nachkommastellen durch ein Zeichen getrennt werden, hier mit small.mark = "_" . Man erkennt an der Ausgabe, dass small.interval_ den default-Wert 5 besitzen muss.

Zeile 11 bis 14: Mit small.interval = 2 kann die Länge der Gruppen in den Nachkommastellen festgelegt werden.

Das Argument drop0trailing

Manchmal sind Nullen, die an einer Zahl mit Nachkommastellen angehängt werden, wichtig um die Anzahl an gültigen Stellen korrekt auszudrücken, manchmal stören sie nur und sollen wieder abgeschnitten werden. Die einfachste Art dies zu steuern bietet das Argument drop0trailing. Eine wichtige Anwendung zeigt das folgende Skript:

v <- 10^(1:3)
v
# [1]   10  100 1000

formatC(x = 1 / v, format = "f", digits = 4)
# "0.1000" "0.0100" "0.0010"

formatC(x = 1 / v, format = "f", digits = 4, drop0trailing = TRUE)
# "0.1"   "0.01"  "0.001"

Zeile 1 bis 3: Wie schon oben wird der Vektor v definiert.

Zeile 5 und 6: Die Kehrwerte der Komponenten von v sollen ausgegeben werden. Mit der Anweisung format = "f", digits = 4 werden in jeder Komponente 4 Nachkommastellen angezeigt. Dabei entstehen einige Nullen, denen keine Ziffer ungleich 0 nachfolgt.

Zeile 8 und 9: Mit drop0trailing = TRUE können die angehängten Nullen wieder entfernt werden.

Das Argument zero.print

Speziell bei Matrizen möchte man oft diejenigen Einträge hervorheben, die ungleich 0 sind. Dann bietet es sich an entweder die Nullen überhaupt nicht darzustellen oder anstelle der Null ein anderes Zeichen zu verwenden. Mit Hilfe des Argumentes zero.print kann man dies bewirken; es kann entweder einen logischen Wert annehmen oder eine Zeichenkette (mit der die Nullen ersetzt werden). Das folgende Skript zeigt typische Beispiele:

m <- diag(x = 1:10)

formatC(x = m, width = 2, zero.print = FALSE)
#     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] " 1" " "  " "  " "  " "  " "  " "  " "  " "  " "  
# [2,] " "  " 2" " "  " "  " "  " "  " "  " "  " "  " "  
# [3,] " "  " "  " 3" " "  " "  " "  " "  " "  " "  " "  
# [4,] " "  " "  " "  " 4" " "  " "  " "  " "  " "  " "  
# [5,] " "  " "  " "  " "  " 5" " "  " "  " "  " "  " "  
# [6,] " "  " "  " "  " "  " "  " 6" " "  " "  " "  " "  
# [7,] " "  " "  " "  " "  " "  " "  " 7" " "  " "  " "  
# [8,] " "  " "  " "  " "  " "  " "  " "  " 8" " "  " "  
# [9,] " "  " "  " "  " "  " "  " "  " "  " "  " 9" " "  
# [10,] " "  " "  " "  " "  " "  " "  " "  " "  " "  "10" 

formatC(x = m, width = 2, zero.print = "--")
#      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] " 1" "--" "--" "--" "--" "--" "--" "--" "--" "--" 
# [2,] "--" " 2" "--" "--" "--" "--" "--" "--" "--" "--" 
# [3,] "--" "--" " 3" "--" "--" "--" "--" "--" "--" "--" 
# [4,] "--" "--" "--" " 4" "--" "--" "--" "--" "--" "--" 
# [5,] "--" "--" "--" "--" " 5" "--" "--" "--" "--" "--" 
# [6,] "--" "--" "--" "--" "--" " 6" "--" "--" "--" "--" 
# [7,] "--" "--" "--" "--" "--" "--" " 7" "--" "--" "--" 
# [8,] "--" "--" "--" "--" "--" "--" "--" " 8" "--" "--" 
# [9,] "--" "--" "--" "--" "--" "--" "--" "--" " 9" "--" 
# [10,] "--" "--" "--" "--" "--" "--" "--" "--" "--" "10"

formatC(x = m, width = 2, zero.print = "-", replace.zero = FALSE)
#     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
# [1,] " 1" " -" " -" " -" " -" " -" " -" " -" " -" " -" 
# [2,] " -" " 2" " -" " -" " -" " -" " -" " -" " -" " -" 
# [3,] " -" " -" " 3" " -" " -" " -" " -" " -" " -" " -" 
# [4,] " -" " -" " -" " 4" " -" " -" " -" " -" " -" " -" 
# [5,] " -" " -" " -" " -" " 5" " -" " -" " -" " -" " -" 
# [6,] " -" " -" " -" " -" " -" " 6" " -" " -" " -" " -" 
# [7,] " -" " -" " -" " -" " -" " -" " 7" " -" " -" " -" 
# [8,] " -" " -" " -" " -" " -" " -" " -" " 8" " -" " -" 
# [9,] " -" " -" " -" " -" " -" " -" " -" " -" " 9" " -" 
# [10,] " -" " -" " -" " -" " -" " -" " -" " -" " -" "10"

Zeile 1: Mit m wird eine Matrix definiert, die nur Einträge auf der Hauptdiagonalen besitzt, alle anderen Einträge sind gleich 0.

Zeile 3 bis 14: Die Matrix m wird mit width = 2, zero.print = FALSE ausgegeben. Der logische Wert zero.print = FALSE sorgt dafür, dass die Nullen nicht dargestellt werden, sondern duch ein Leerzeichen ersetzt werden. Man erkennt, dass die Anweisung width = 2 nur für Hauptdiagonalelemente wirksam ist.

Zeile 16 bis 27: Anstelle eines logischen Wertes kann das Argument zero.print auch eine Zeichenkette erhalten. Da auf der Hauptdiagonalen maximal zwei Zeichen stehen, wird eine Zeichenkette der Länge zwei gewählt (man kann hier natürlich auch zwei Leerzeichen verwenden). Jetzt hat die Anweisung width = 2, zero.print = "--" den gewünschten Effekt: alle Elemente der Matrix m besitzen die identische Breite und die Hauptdiagonalelemente sind sofort sichtbar.

Zeile 29 bis 40: Die Anweisung aus Zeile 16 hat den Nachteil, dass man die nötige Feldbreite kennen muss. Indem man setzt replace.zero = FALSE , wird die Breite von zero.print = "-" automatisch an die maximale Breite der Hauptdiagonalelemente angepasst (die Felder werden durch Leerzeichen aufgefüllt).

Die wichtigsten Unterschiede zwischen format() und formatC()

Die Eingabewerte

Die folgenden beiden Skripte zeigen die Eingabewerte der beiden Funktionen format() und formatC(). Man erkennt, dass sie in vielen Eingabewerten übereinstimmen; natürlich haben sie dann auch identisches Verhalten.

Der große Unterschied liegt in den Argumenten format = NULL und flag = "" von formatC(), die die Funktion format() nicht besitzt. Mit diesen Argumenten wird erreicht, dass formatC() ein ähnliches Verhalten hat wie die Formatierung in der Programmiersprache C. Ein spezieller Unterschied, der sich daraus in ihrem Verhalten ergibt, wird unten besprochen (Verarbeitung von Vektoren).

Eingabewerte von format():

format(x, trim = FALSE, digits = NULL, nsmall = 0L,
        justify = c("left", "right", "centre", "none"),
        width = NULL, na.encode = TRUE, scientific = NA,
        big.mark = "", big.interval = 3L,
        small.mark = "", small.interval = 5L,
        decimal.mark = getOption("OutDec"),
        zero.print = NULL, drop0trailing = FALSE, ...)

Eingabewerte von formatC():

formatC(x, digits = NULL, width = NULL,
        format = NULL, flag = "", mode = NULL,
        big.mark = "", big.interval = 3L,
        small.mark = "", small.interval = 5L,
        decimal.mark = getOption("OutDec"),
        preserve.width = "individual",
        zero.print = NULL, replace.zero = TRUE,
        drop0trailing = FALSE)

Die Funktion format() ist generisch implementiert

Die Funktion formatC() ist nicht generisch implementiert; der Speichermodus des Eingabewertes x bestimmt ihr Verhalten. Dagegen ist format() generisch implementiert und es gibt Implementierungen für spezielle R-Objekte (wie Dataframe oder Faktor).

Daher ist bei komplizierten Datenstrukturen das Verhalten der beiden Funktionen unterschiedlich, was hier nicht im Detail diskutiert wird (weitere Informationen finden sich in der Dokumentation). Das folgende Beispiel soll den Unterschied für ein Dataframe und einen Faktor zeigen:

#    Dataframe:

v <- (1:3) * pi
m <- cbind( v1 = v, v2 = 1 / v )

df <- as.data.frame(m)
df
#         v1        v2
# 1 3.141593 0.3183099
# 2 6.283185 0.1591549
# 3 9.424778 0.1061033

format(x = df)
#         v1        v2
# 1 3.141593 0.3183099
# 2 6.283185 0.1591549
# 3 9.424778 0.1061033

formatC(df)
# Error in is.finite(x) : default method not implemented for type 'list'
# In addition: Warning message:
# In formatC(df) : Klasse von 'x' wurde verworfen

#    Faktor:

f <- factor(x = c(1, 1, 2, 2, 3))
f
# [1] 1 1 2 2 3
# Levels: 1 2 3

format(x = f)
# "1" "1" "2" "2" "3"

formatC(x = f)
# [1] "1" "1" "2" "2" "3"
# attr(,"levels")
# [1] "1" "2" "3"

Verarbeitung von Vektoren

Bei der Verwendung der Funktionen format() und formatC() für Vektoren sollte man beachten, dass

Die folgenden Beispiele sollen dies demonstrieren:

z <- c(0.5, 0.55, 0.555, 0.5555)

format(z, digits = 3)
# [1] "0.500" "0.550" "0.555" "0.555"

format(z, digits = 5)
# "0.5000" "0.5500" "0.5550" "0.5555"

formatC(z, digits = 3)
# " 0.5"  "0.55"  "0.555" "0.555"

formatC(z, format = "f", digits = 3)
# "0.500" "0.550" "0.555" "0.555"

formatC(z, format = "f", digits = 5)
# "0.50000" "0.55000" "0.55500" "0.55550"

Aufgabe: Beschreiben Sie, wie in obigen Beispielen die Anzahl der Nachkommastellen und die Feldbreite aus den Formatierungsanweisungen abgeleitet werden.

Die Funktion prettyNum()

Die Funktion prettyNum() besitzt nahezu die identischen Eingabewerte wie formatC() und wird von dieser auch verwendet, wenn der Eingabewert x aus Zahlen besteht (siehe Skript unten). In der Dokumentation findet sich prettyNum() im Paket base unter formatC(). Die Funktion prettyNum() wird hier nicht besprochen.

prettyNum(x, big.mark = "", big.interval = 3L,
        small.mark = "", small.interval = 5L,
        decimal.mark = getOption("OutDec"), input.d.mark = decimal.mark,
        preserve.width = c("common", "individual", "none"),
        zero.print = NULL, replace.zero = FALSE,
        drop0trailing = FALSE, is.cmplx = NA,
        ...)