Neue native Nacheinanderausführungssyntax nutzen?

Wie rufe ich R-Funktionen auf, wie selektiere ich Daten, ich weiß nicht genau ....

Moderatoren: EDi, jogo

Antworten
bigben
Beiträge: 2771
Registriert: Mi Okt 12, 2016 9:09 am

Neue native Nacheinanderausführungssyntax nutzen?

Beitrag von bigben »

Hallo,

mit R Version 4.1 ist die native Pipe als denkbare Konkurrenz zur magrittr Pipe eingeführt worden und ich frage mich, welchen Sinn die zweite Pipe hat und ob sie sich durchsetzen wird. Klar ist, sie funktioniert anders: "The simple form of the forward pipe inserts the left-hand side as the first argument in the right-hand side call."

Das kann man beispielsweise beim Benchmarking sehen:

Code: Alles auswählen

library(microbenchmark)
library(magrittr)
bm <- microbenchmark(
         1:500 |> sqrt(),
         1:500 %>% sqrt,
         times = 10000
      )
print(bm)
boxplot(bm)
gibt bei mir aus:

Code: Alles auswählen

> print(bm)
Unit: microseconds
           expr min  lq    mean median  uq    max neval
    sqrt(1:500) 3.5 4.0 6.56177    4.3 5.3 9544.4 10000
 1:500 %>% sqrt 5.7 6.3 9.56969    6.7 8.5 6211.7 10000
Man erkennt an der Ausgabe, dass die native Pipe vor der Evaluation durch microbenchmark angewendet wurde, während die magrittr Pipe jedes Mal neu evaluiert werden muss. Dementsprechend läuft die native Pipe dann auch um Nanosekunden schneller. Nagut, ich habe Schwierigkeiten mir vorzustellen, unter welchen Umständen das ausschlaggebend wäre. Der Geschwindigkeitsvorteil durch das Weglassen eines library Aufrufs ist da -wenn überhaupt- wahrscheinlich eher zu merken.

Die Dokumentationsseite zur Pipe schreibt "The forward pipe operator is motivated by the pipe introduced in the magrittr package, but is more streamlined. " Das wird Athomas gefallen, dass hier auf die Quelle des Gedankens verwiesen wird. Aber kann mir vielleicht jemand erklären, was streamlined in diesem Kontext heißt?

Der von jogo unter Aktuelles zum Thema verlinkte Blog schreibt über die native Pipe:
The new operator is nicer to type, and should be both more efficient and easier to debug, than the {magrittr} pipe.
Sieht jemand bessere Debugging Möglichkeiten? Ich gebe gerne zu, dass Debugging bei mir oft das Einfügen von print-Kommandos ist. Auf dem Niveau sehe ich die Vorteile nicht, aber ich könnte mir schon denken, dass bei der Verwendung von debug() entstehen?

Auf der Gegenseite der Waage hat magrittr einfach einen riesigen Popularitätsvorsprung. Zigtausende Blogs und Erklärungen im Netz, die es schon nutzen und dann noch den Punkt-Operator.

Wie seht Ihr das?

LG,
Bernhard
---
Programmiere stets so, dass die Maxime Deines Programmierstils Grundlage allgemeiner Gesetzgebung sein könnte
jogo
Beiträge: 2085
Registriert: Fr Okt 07, 2016 8:25 am

Re: Neue native Nacheinanderausführungssyntax nutzen?

Beitrag von jogo »

Ich halte die pipes für durchaus brauchbar -- vielleicht bin ich vorgeschädigt, weil ich seit über 40 Jahre mit UNIX-ähnlichen Betriebssystemen zu tun habe. Da die pipes seit 4.1 zum normalen Sprachumfang von R gehören, kann sie jeder nutzen -- muss aber nicht.

Wie immer kann man auch bei der Nutzung von pipes übertreiben; hier eine entsprechende Spielerei:

Code: Alles auswählen

set.seed(42)
sum(abs(apply(matrix(rnorm(100), 10), 1, sum)))

# vs. 

set.seed(42)
100 |> rnorm() |> matrix(10) |> apply(1, sum) |> abs() |> sum()
Die Verwendung von pipes kann die Lesbarkeit verbessert, wahrscheinlich macht es die geeignete Mischung:

Code: Alles auswählen

set.seed(42)
M <- matrix(rnorm(100), 10)
apply(M, 1, sum) |> sum(abs()) ## Fehler!

set.seed(42)
M <- matrix(rnorm(100), 10)
apply(M, 1, sum) |> abs() |> sum()

set.seed(42)
M <- matrix(rnorm(100), 10)
sum(abs(apply(M, 1, sum)))

set.seed(42)
matrix(rnorm(100), 10) |> apply(1, sum)  |> abs() |> sum()
Nicht überall funktionieren pipes:

Code: Alles auswählen

3  |> '+'(4)  ## Fehler!
'+'(3, 4)
Gruß, Jörg
bigben
Beiträge: 2771
Registriert: Mi Okt 12, 2016 9:09 am

Re: Neue native Nacheinanderausführungssyntax nutzen?

Beitrag von bigben »

Hallo Jörg,

ja, so eine einfache Funktion wie `+` braucht man gelegentlich. Dass das nicht geht, finde ich lästig.

Es ist ja ein wenig her, seit ich das oben geschrieben habe. Ich finde inzwischen auch, dass die Pipe manchmal passt und manchmal nicht so sehr. Ich glaube, ich nutze sie lieber für den schnellen Einzeiler, das improvisiert interaktive, als für längerlebige Funktionen. Wahrscheinlich ist das genau falsch herum, sie nicht dort zu nutzen, wo sie ihren vermeintlichen Lesbarkeitsvorteil ausspielen kann?

Noch eine Randbemerkung dazu: Ich probiere seit heute einen neuen Font in RStudio aus: Der Font heißt Fira Code und man findet ihn auf GitHub: https://github.com/tonsky/FiraCode
Fira Code nutzt Ligaturen um Zeichenkombinationen wie `<=` und `!=` um, ohne den Code zu ändern, stattdessen `≤` und `≠` darzustellen. Falls ich das im Verlauf gut finde, erwächst daraus ein kleiner Vorteil für die native Pipe, weil diese eben auch zu einem schönen Dreieck-Einzelzeichen zusammengefasst wird und die magrittr Pipe eben nicht. Dein obiges Beispiel sieht bei mir derzeit so aus:
Screenshot 2023-08-07 192723.png
Was ich in magrittr schön finde und nicht verstehe, dass es weder ins tidyverse noch in die native Version übernommen wurde, ist die %<>% pipe. Die finde ich nützlich. Ich gebe zu, es gibt wichtigeres.

Viele Grüße,
Bernhard
---
Programmiere stets so, dass die Maxime Deines Programmierstils Grundlage allgemeiner Gesetzgebung sein könnte
Antworten