Textverarbeitung mit R: Die Funktion paste() zum Zusammenfügen von Vektoren als Erweiterung von paste0()

Die Funktion paste() dient ähnlich wie die Funktion paste0() dazu, mehrere Vektoren in Zeichenketten zu verwandeln, die entsprechenden Komponenten zusammenzufügen (1.Schritt) und diese zu einer einzigen Zeichenkette zusammenzusetzen (2. Schritt). In beiden Schritten kann eine Zeichenkette als Trennungszeichen eingefügt werden (die Argumente sep beziehungsweise collapse). Die Funktion paste0() besitzt kein Argument sep; für Aufgaben, die sich auch mit paste0() erledigen lassen, können dadurch mit paste() einfachere Quelltexte geschrieben werden. Beispiele und Spezialfälle werden erläutert.

Einordnung des Artikels

Gründliche Kenntnisse über die Funktion paste0() werden hier benötigt und vorausgesetzt.

Einführung

Die Funktion paste() bildet eine Erweiterung der Funktion paste0() und wird ebenso eingesetzt, um Vektoren zusammenzufügen. Die Eingabewerte beider Funktionen sind im folgenden Skript zu sehen:

paste (..., sep = " ", collapse = NULL)
paste0(..., collapse = NULL)

Man kann aus den Eingabewerten bereits erahnen, dass die Funktion paste() auf die Funktion paste0() zurückgreift, wenn man für das Argument sep das Leerzeichen einsetzt, also sep = "" . Andernfalls liefert paste() Funktionalitäten, die über paste0() hinausgehen oder mit paste0() nur umständlich zu realisieren sind. Und man soll die Funktion paste0() verwenden, wenn die weiter gehende Funktionalität von paste() nicht benötigt wird – das Skript wird dann natürlich schneller ausgeführt.

Die Bedeutung des Argumentes sep = " " und ihr Zusammenspiel mit den anderen Argumenten wird in den folgenden Abschnitten erklärt.

Abbildung 1 zeigt nochmals die Arbeitsweise von paste0():

1. Schritt: Von den Vektoren, die an das Argument ... übergeben werden, werden entsprechende Komponenten zusammengefügt und in Zeichenketten verwandelt.

2. Schritt: Anschließend wird das Argument collapse als Trennungszeichen zwischen den Komponenten des soeben erzeugten character-Vektors eingefügt und eine einzige Zeichenkette erzeugt. (Wenn collapse als "Trennungszeichen" bezeichnet wird, ist dies irreführend: collapse muss nicht ein einzelnes Zeichen sein, sondern kann selbst eine Zeichenkette sein.)

Abbildung 1: Darstellung der Arbeitsweise von paste0(), wenn mehrere Vektoren zusammengefügt und ein Trennungszeichen eingefügt werden soll.Abbildung 1: Darstellung der Arbeitsweise von paste0(), wenn mehrere Vektoren zusammengefügt und ein Trennungszeichen eingefügt werden soll.

Analog zeigt jetzt Abbildung 2 die Arbeitsweise von paste():

1. Schritt: Wieder werden die entsprechenden Komponenten der Eingabe-Vektoren aus ... zusammengefügt; jetzt wird aber als Trennungszeichen das Argument sep eingesetzt. Es entsteht ein Vektor von Zeichenketten (hellgrün in Abbildung 2).

2. Schritt: Die Komponenten dieses Vektors werden mit collapse als Trennungszeichen zu einer einzigen Zeichenkette zusammengefügt.

(Wieder ist hier mit "Trennungszeichen" gemeint, dass auch eine Zeichenkette im Argument sep beziehungsweise collapse verwendet werden darf.)

Abbildung 2: Darstellung der Arbeitsweise von paste(), wenn mehrere Vektoren zusammengefügt werden. Das Argument sep wird als Trennungszeichen zwischen den entsprechenden Komponenten verwendet (1. Arbeitsschritt). Im zweiten Arbeitsschritt wird das Argument collapse als Trennungszeichen verwendet, wenn der soeben erzeugte Vektor zu einer Zeichenkette zusammengesetzt wird.Abbildung 2: Darstellung der Arbeitsweise von paste(), wenn mehrere Vektoren zusammengefügt werden. Das Argument sep wird als Trennungszeichen zwischen den entsprechenden Komponenten verwendet (1. Arbeitsschritt). Im zweiten Arbeitsschritt wird das Argument collapse als Trennungszeichen verwendet, wenn der soeben erzeugte Vektor zu einer Zeichenkette zusammengesetzt wird.

Ein typisches Beispiel

Im Hexadezimalsystem gibt es 16 Ziffern: 0, 1, 2, ..., 15. Um die 6 Ziffern 10, 11, ..., 15 von zweistelligen Zahlen unterscheiden zu können, werden die Ziffern durch Buchstaben ersetzt. Es soll die Zeichenkette erzeugt werden, die diese Zuordnung herstellt (siehe auch Abbildung 2):

# "A = 10 | B = 11 | C = 12 | D = 13 | E = 14 | F = 15"

Um diese Zeichenkette mit paste() zu erzeugen,

Das vollständige Skript lautet:

numbers <- (10:15)
hexletters <- c('A', 'B', 'C', 'D', 'E', 'F')

paste(hexletters, numbers, sep = " = ", collapse = " | ")
# "A = 10 | B = 11 | C = 12 | D = 13 | E = 14 | F = 15"

Die Vektoren aus Zeile 1 und 2 müssen natürlich nicht in einer Variable abgespeichert werden; sie werden aber in den folgenden Abschnitten mehrfach benutzt und dann nicht mehr gezeigt.

Der default-Wert des Argumentes sep

Die Tatsache, dass sich paste0() und paste() lediglich im Argument sep unterscheiden, kann leicht zu einem Missverständnis führen: man ist geneigt anzunehmen, dass bei einer Anwendung von paste(), in der sep nicht gesetzt wird, das gleiche Ergebnis entsteht wie bei der entsprechenden Anwendung von paste0(). Dies ist falsch.

Das Missverständnis entsteht wenn man übersieht, dass das Argument sep = " " als default-Wert das Leerzeichen besitzt. Das folgende Skript zeigt den Unterschied zwischen paste() und paste0():

paste(hexletters, numbers, collapse = " | ")
# "A 10 | B 11 | C 12 | D 13 | E 14 | F 15"

paste0(hexletters, numbers, collapse = " | ")
# "A10 | B11 | C12 | D13 | E14 | F15"

paste(hexletters, numbers, sep = "", collapse = " | ")
# "A10 | B11 | C12 | D13 | E14 | F15"

Zeile 1 und 2: Die Buchstaben für die Ziffern im Hexadezimalsystem und die Zahlen 10, 11, ..., 15 werden mit paste() zusammengefügt, wobei sep nicht gesetzt wird und wie in Abbildung 2 collapse = " | " gesetzt wird. Die 6 Buchstaben und die entsprechenden Zahlen werden durch ein Leerzeichen getrennt.

Zeile 4 und 5: Übergibt man die Argumente aus Zeile 1 an paste0(), so fehlt dieses Leerzeichen zwischen Buchstaben und Zahlen.

Zeile 7 und 8: Setzt man in paste() das Argument sep = "" (leerer String), so erhält man das Ergebnis der Anwendung von paste0() aus Zeile 4.

Man kann diese Skripte auch so lesen: immer wenn sep = "" gesetzt werden soll, verwendet man besser paste0().

Das Argument dot-dot-dot

In Abbildung 2 werden zwei Vektoren an das Argument dot-dot-dot übergeben; unklar ist vielleicht, welches Verhalten paste() zeigt, wenn nur ein Vektor oder mehr als zwei Vektoren an ... übergeben werden. Diese Fälle wurden schon für die Funktion paste0() untersucht – die Funktion paste() zeigt hier kein abweichendes Verhalten. Die folgenden Beispiele sollten daher ohne ausführliche Erklärung verständlich sein:

numbers <- (10:15)
hexletters <- c('A', 'B', 'C', 'D', 'E', 'F')
hexletters.small <- c('a', 'b', 'c', 'd', 'e', 'f')

paste(hexletters, collapse = " | ")
# "A | B | C | D | E | F"

paste(hexletters)
# "A" "B" "C" "D" "E" "F"

paste(hexletters, hexletters.small, numbers, sep = " = ", collapse = " | ")
# "A = a = 10 | B = b = 11 | C = c = 12 | D = d = 13 | E = e = 14 | F = f = 15"

Zeile 1 bis 3: Definition der Vektoren, die später eingesetzt werden.

Zeile 5 bis 9: Wird nur ein Vektor an ... übergeben, so wird entweder eine einzige Zeichenkette erzeugt (wenn das Argument collapse gesetzt ist, siehe Zeile 5) beziehungsweise es wird ein Vektor von Zeichenketten erzeugt (und dieser Vektor besitzt die Länge des Eingabe-Vektors, siehe Zeile 8).

Dieses Verhalten kann man leicht mit Abbildung 2 erklären: Im ersten Arbeitsschritt werden die Komponenten des Eingabe-Vektors in Zeichenketten verwandelt. Je nachdem ob collapse gesetzt ist oder nicht, wird der zweite Arbeitsschritt ausgeführt.

Zeile 11 und 12: Werden an ... mehr als zwei Vektoren übergeben, werden wiederum im 1. Arbeitsschritt (siehe Abbildung 2) alle entsprechenden Komponenten mit dem Trennungszeichen sep zusammengefügt. Der 2. Arbeitsschritt wird dann wie üblich ausgeführt.

Bei unterschiedlichen Längen der Eingabe-Vektoren ist wieder der recycling-Mechanismus zu beachten, der bei paste0() erklärt wurde.

Beispiel: Erzeugen einer mediawiki-Tabelle

Als weitere Anwendung der Funktion paste() soll gezeigt werden, wie man den Quelltext für eine Tabelle erzeugen kann, in der mehrere Vektoren dargestellt werden. Als Auszeichnungssprache wird mediawiki verwendet. Hat man die Vorgehensweise verstanden, ist es ganz leicht, den Quelltext in anderen Auszeichnungssprachen zu erzeugen.

Die folgende Tabelle zeigt die Zuordnung der Buchstaben im Hexadezimalsystem zu den Ziffern, wenn sie als Zahlen im Dezimalsystem dargestellt werden.

A 10
B 11
C 12
D 13
E 14
F 15

In mediawiki lautet der Quelltext für die Tabelle:

{|
|-
| A
| 10
|-
| B
| 11
|-
| C
| 12
|-
| D
| 13
|-
| E
| 14
|-
| F
| 15
|}

Vergleicht man diesen Quelltext mit Abbildung 2, so kann man leicht ablesen, wie die Funktion paste() hier eingesetzt werden muss:

  1. An das Argument ... werden die Vektoren übergeben (Hexadezimalzahlen und Dezimalzahlen).
  2. Zwischen je zwei entsprechenden Komponenten der Vektoren steht: ein Zeilenumbruch, das Zeichen | sowie ein Leerzeichen; daher wird gesetzt: sep = "\n| " .
  3. Um die Zeilen der Tabelle zu verbinden, benötigt man: einen Zeilenumbruch, das Zeichen |- , einen weiteren Zeilenumbruch, das Zeichen | und ein Leerzeichen; insgesamt also collapse = "\n|-\n| " .
  4. Jetzt fehlen noch der Beginn und das Ende der Tabelle, also die Zeichen "{|\n|-\n| " und "\n|}" ; sie umschließen die in den ersten 3 Schritten erzeugte Tabelle, wofür paste0() eingesetzt wird (siehe Zeile 2 unten).

Der gesamte Quelltext lautet:

mdw.table <- paste(hexletters, numbers, sep = "\n| ", collapse = "\n|-\n| ")
mdw.table <- paste0("{|\n|-\n| ", mdw.table, "\n|}")
cat(mdw.table)

Die Ausgabe mit cat() erfolgt auf der Konsole; es ist natürlich einfach, den mediawiki-Quelltext in eine Datei umzuleiten.

Es ist jetzt leicht, die Anweisungen zum Erzeugen der mediawiki-Tabelle in einer Funktion zu kapseln; sie besitzt hier den Namen mediawikitable(). Eingabewerte sind die Vektoren, die in der Tabelle als Spalten gezeigt werden sollen. Sie werden im Argument ... an die Funktion übergeben und dann an die Funktion paste() weitergereicht. Das folgende Skript zeigt den Quelltext der Funktion (Zeile 1 bis 3) sowie ihren Aufruf, um obige Tabelle zu erzeugen (Zeile 5):

mediawikitable <- function(...){
  return( paste0("{|\n|-\n| ", paste(..., sep = "\n| ", collapse = "\n|-\n| "), "\n|}") )
}

mediawikitable(hexletters, numbers)

Die Funktion cat() kann jetzt wieder verwendet werden, um den erzeugten String anzuzeigen (um die Zeilenumbrüche sichtbar zu machen). Und es ist nicht schwer, die Funktion mediawikitable(...) so umzubauen, dass der Quelltext optional in eine Datei geschrieben wird.

Aufgabe: Implementieren Sie die Funktion mediawikitable() so, dass die eingegebenen Vektoren nicht spaltenweise sondern zeilenweise in der Tabelle dargestellt werden.