Data.table: Integration mit magrittr

Erstellt am 5. Juli 2015  ·  39Kommentare  ·  Quelle: Rdatatable/data.table

Dies ist ein Feature Request im Anschluss an die Diskussion in der Mailingliste .

Ich denke, es wäre nützlich, so etwas als Kurzform zu haben:

DT[, a %<>% some.function] 

Bis jetzt muss man tippen

DT[, a := a %>% some.function]

oder ohne magrittr

DT[, a := some.function(a)]

Dies ist besonders wichtig, wenn a durch eine Variable mit langem Namen ersetzt wird, die dann schwer einzugeben und zu lesen ist. Ich denke, hier gibt es erhebliche Einsparungen bei der (Programmierer-)Effizienz, insbesondere bei längeren Variablennamen.

Hilfreichster Kommentar

Zusammenfassend, damit das Problem schließlich gelöst werden kann.

Alles, was wir brauchen, ist die folgende Übersetzung.

DT[, a %<:>% fun] ## or "%:>%"

DT[, a := fun(a)]

Ist das richtig?

wie soll es sich verhalten, wenn a kein Symbol sondern eine Zeichenvariable ist?

DT[, "a" %<:>% fun]

DT[, "a" := fun(a)]   ## this?
DT[, "a" := fun("a")] ## or this?

Was ist, wenn seine Länge nicht 1 ist?

DT[, c("a","b") %<:>% fun]

DT[, c("a","b") %<:>% fun(a, b)]
DT[, c("a","b") %<:>% fun("a","b")]
DT[, c("a","b") %<:>% lapply(list(a, b), fun)]
DT[, c("a","b") %<:>% lapply(c("a", "b"), fun)]

Persönlich würde ich es schließen, da es nicht behoben wird, da es viel Komplexität hinzufügt und kein neues Problem löst.
Ich sehe darin Einigkeit, also schließen wir, wir können immer wieder öffnen, wenn es wirklich nötig ist.

Alle 39 Kommentare

DT[, a := some.function(a)]

Funktioniert einwandfrei

Aber imho

Complicated_data_table_variable_name[, a_very_very_very_very_long_variable_name := some.function(a_very_very_very_very_long_variable_name)]

ist nicht ganz in Ordnung. Ich mag die Idee, diese Komfortfunktion hinzuzufügen.

Aber vielleicht wäre %:>% besser als %<>% ?

Sie sollten nicht so seltsame Namen in Ihrem Datensatz haben. Es ist sowohl unpraktisch als auch kaum zu warten. Abgesehen davon können Sie den Spaltennamen in einer Variablen speichern und dann Folgendes tun:

shortname <- "a_very_very_very_very_long_variable_name"
DT[, (shortname) := some.function(get(shortname))]

Sie haben Recht, aber selbst bei Variablen mit mittlerer Länge finde ich die magrittr-Syntax immer noch viel bequemer zum Lesen und Schreiben. Das ist jedenfalls nur meine persönliche Meinung.

Ich finde, dass es manchmal besser ist, lange Variablennamen in komplexen Datensätzen zu verwenden, um deutlich zu machen, was in einer Variablen gespeichert ist. Es ist eine Frage der persönlichen Präferenz. Komfortfunktionen sind per Definition nicht erforderlich, um eine Aufgabe auszuführen, sie machen es nur schneller zu codieren und oft einfacher zu verstehen. Ich habe keinen Zweifel, dass diese Funktion für viele Benutzer von Nutzen sein würde. Aber ich verstehe auch, wenn die data.table-Entwickler keine (zu viele) Komfortfunktionen implementieren/pflegen wollen, muss man irgendwo eine Grenze ziehen ;)

Für diejenigen unter Ihnen, die diesen Thread abonniert haben, ignorieren Sie bitte den letzten Kommentar (jetzt gelöscht). Es war albern.

Aufbauend auf dem Kommentar von @and3k sehe ich einen Wert von:

DT[, a %:=>% some.function]

Denke, das liest sich besser (dh ein := und %>% zusammen). Es ist eine "glückliche Pfeife"? Ich bin ein Fan von Bemühungen, die Wiederholung von Variablennamen zu reduzieren, wie hier geschrieben: http://stackoverflow.com/a/10758086/403310

Der => Teil des :=> Operators hat eine zusätzliche Bedeutung, vielleicht :=: ?

DT[, a %:=:% some.function]

oder :=. das direkt als := abgebildet wird, gefolgt von . das an Spaß übergeben wird

Welche zusätzliche Bedeutung hat => ? Das > ist nett, weil es die Übergabe des LHS als Argument an RHS vermittelt. Aus diesem Grund wurde Hadley vom ursprünglichen %.% in %>% geändert.

Mein Verständnis war, dass ein Hauptgrund für den Wechsel zu %>% bestand, dass es viel einfacher ist zu tippen als %.% (ich vermute, dass ich oft versuche, %.% würde versehentlich zu %>% ).

Ich meine den Operator _größer oder gleich_.
Und was ist mit %:>% ? Dies wäre einfacher zu tippen als %:=>% oder %:=:% .
and3k erwähnen das bereits oben.

Meine Stimme ist für %:>% oder nur :> .

Die % 's sind nur da, weil R keine freien Infixoperatoren zulässt, oder? Könnte genauso gut die Operatoren in DT[] sparsam halten.

Ich hatte den Tippaspekt nicht berücksichtigt, dh das Halten der Umschalttaste für alle Zeichen im Operator ist einfacher, nehme ich an. Macht Sinn.
:> parst leider nicht. Was sich in [...] befindet, muss immer noch eine gültige R-Syntax sein (alle Argumente werden immer geparst, bevor sie unevaluiert an die Funktion übergeben werden), damit wir keine neuen Operatoren in [...] erstellen können, müssen wir immer noch umbrechen mit % 's.
Ok dann sieht %:>% für mich auch gut aus. Es wäre nicht so, als ob es eine große Priorität hätte, aber es wäre nicht schwer zu implementieren und es wäre gut, darüber diskutiert zu werden.

Danke, %:>% sieht für mich gut aus.

Nur neugierig, warum analysiert :> nicht, während := innerhalb von [....] analysiert? := ist auch keine gültige R-Syntax, oder?

@my-R-help es ist eine gültige Syntax, siehe diese Warum ist := als Infix-Operator erlaubt?

+1 Ich stimme der OP-Funktionsanfrage und der Verwendung der magrittr-Syntax zu. Es ist aus mehreren Gründen die beste und naheliegendste Wahl.

  • Die Leute nutzen DT bereits intensiv mit itmagrittr
  • Die Syntax von magrittr ist an dieser Stelle allgegenwärtig ... könnte sogar einen eigenen rstudio-Hotkey bekommen ... und jede andere syntaktische Wahl wird wahrscheinlich in Verwirrung enden.

Ich ermutige Sie dringend, diese FR nicht zu überdenken, indem Sie einen neuen Operator einführen, dessen Wahl genauso willkürlich wie die Wahl von magrittr ist.

Ich ermutige Sie dringend, diese FR nicht zu überdenken, indem Sie einen neuen Operator einführen, dessen Wahl genauso willkürlich wie die Wahl von magrittr ist.

@ctbrown Der Vorschlag ist für einen Pipe-Operator, der etwas anderes macht als das Vanilla %>% von magrittr, ein Paket, das auch mehrere andere Pipe-Operatoren enthält. Solange es nicht mit diesen kollidiert, was ist das Problem?

Ich denke, die FR-Anfrage des OP war ausreichend klar, dh
um %<>% speziell als kombiniertes-Forward-Pipe-and-Assignment zu verwenden
Operator. Vermutlich liegt das daran, dass magrittr bereits %<>% für
genau diesen Zweck. Da magrittr die dominierende Pfeife zu sein scheint
Implementierung und viele Leute scheinen %<>% zu verwenden, meine Schüler und
Kollegen darunter. Es macht keinen Sinn, einen anderen vorzustellen
Betreiber für genau den gleichen Zweck. Es ist viel sinnvoller, a . zu wählen
Syntax, die sich an dem ausrichtet, was die Community erfahren hat oder bereits hat
angenommen. Siehe meinen Punkt zur Allgegenwart.

Lassen Sie mich Sie fragen, was Sie sich von der Einführung eines anderen Betreibers erhoffen
das genau die gleiche Funktion in einem anderen Kontext erfüllt? ich kann nicht sehen
irgendein Vorteil. Jeder von Ihnen gewählte Operator ist so willkürlich wie der von magrittr.
Macht es also keinen Sinn, das ganze System einfach weniger willkürlich zu machen
Magrittrs Führung hier folgen, anstatt noch eine weitere willkürlich zu machen
syntaktische Entscheidung?

Am Do, 27.10.2016 um 11:41 Uhr, franknarf1 [email protected]
schrieb:

Ich ermutige Sie dringend, dieses FR nicht zu überdenken, indem Sie ein neues einführen
Operator, dessen Wahl genauso willkürlich wie magrittrs Wahl war.

@ctbrown https://github.com/ctbrown Der Vorschlag ist für einen
das macht was anderes als die Vanille %>% von magrittr, a
Paket, das auch mehrere andere Pipe-Operatoren enthält. Solange es nicht
Konflikt mit einem von denen, was ist das Problem?


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/Rdatatable/data.table/issues/1208#issuecomment -256732710,
oder den Thread stumm schalten
https://github.com/notifications/unsubscribe-auth/AC5xaxIp36dTUCz9d5a5mU7CJUV6PaxCks5q4PBDgaJpZM4FSJR5
.

Wird %<>% per Referenz zugewiesen? Wenn nicht, dann tun sie _nicht_ genau dasselbe.

Technisch gesehen hast du recht, magrittr's %<>% ordnet nicht per Referenz zu,
aber das ist nebensächlich. Innerhalb der Erwartungen der Benutzer gibt es keine
Unterschied. Die Zuweisung, ob nach Referenz oder nach Wert, ist ein
Implementierungsproblem kein Schnittstellenproblem. Das OP hat vorgeschlagen angenommen
magrittr-Schnittstelle und schlug die Implementierung nicht unbedingt vor.
Ich habe den Vorteil im OP-Vorschlag gesehen. Siehe die Gründe oben. Ich tu nicht
Sehen Sie die Gründe für die Annahme von etwas wie '%:>% or anything as arbitrary. The merit of this has not been articulated. The %<>%`
Betreiber existiert bereits und wird von magrittr aktiv gefördert (12
beliebtes Paket nach METACRAN.) So viel wie alles scheint dies zu sein
der Standard sein (innerhalb der R-Community). Das Schöne am Folgen
etablierte Praxis reduziert die Verwirrung der Benutzer und die Notwendigkeit von
umfassende Dokumentation. Du bekommst: "Oh, das ist das gleiche wie magrittr, ich
kennt diese Vorlaufrohre und macht eine Aufgabe", statt "was ist das?
seltsam %:>%? Ist das ein neues Clown-Emoticon?"

Am Do, 27. Oktober 2016 um 14:18, Michael Chirico [email protected]
schrieb:

Wird %<>% per Referenz zugewiesen? Wenn nicht, dann tun sie es tatsächlich _nicht_
genau das gleiche.


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/Rdatatable/data.table/issues/1208#issuecomment -256772769,
oder den Thread stumm schalten
https://github.com/notifications/unsubscribe-auth/AC5xa3ssE14PcamL2U9HlvCdfA8-7Iz8ks5q4RUagaJpZM4FSJR5
.

Innerhalb der Erwartungen der Benutzer gibt es keinen Unterschied.

Erstens glaube ich nicht, dass das stimmt und dass Sie für alle Benutzer sprechen; Ich bin zum Beispiel ein Benutzer. Zweitens, wenn dies zutrifft, sollten diese Benutzer den Unterschied kennenlernen, wenn sie lernen, data.table zu verwenden.

Deine "oben genannten Gründe" sind für mich nicht stichhaltig. Es ist nicht irgendwie gegen magrittr, einen nicht überlappenden Pipe-Operator zu implementieren, um eine bestimmte, aber verwandte Sache zu tun. Für mich -- und dies ist nur mein Eindruck, genauso wie alles, was Sie gesagt haben, von Ihnen stammt -- scheint dies perfekt mit der "etablierten Praxis" von magrittr zu vereinen (die ich fast so oft verwende wie data.table ).

Es ist durchaus möglich, dass die Verwendung in diesem Kontext mehreren Objekten (Spalten) gleichzeitig zugewiesen wird, was sich sicherlich von %<>% ..? Ich meine

DT[, (cols) %:>% lapply(as.character) ]

Und abgesehen davon, dass wir durch Referenz modifizieren und möglicherweise mehrere Dinge gleichzeitig ändern, haben wir die Tatsache, dass wir einen Teil eines Dings (die data.table) ändern, was sich stark von %<>% .

Wie auch immer, da die Entwickler keine Anzeichen dafür gezeigt haben, diese Aufgabe in absehbarer Zeit zu erledigen (indem sie diese FR mit einer Priorität oder einem Meilenstein markieren), wie wäre es, wenn sie tatsächlich voranschreitet?

@ctbrown _by-reference_ unterscheidet sich nicht nur in der Implementierung, sondern muss von _by-value_-Funktionen in der Benutzeroberfläche unterschieden werden. Das ist der ganze Sinn der set* Funktionen und des := Operators in data.table, um den Benutzern klar zu kommunizieren, was die Eingabe einer Funktion tatsächlich verändert. Schwierig, nach so kurzer Zeit einen Standard innerhalb der R-Community zu beurteilen, R-Anwendungen werden seit Jahrzehnten geschrieben und es ist noch zu früh, um über einen "neuen Standard" zu urteilen, der letztendlich AFAIK über Codeformatierung (Nesting/Unnesting) ist. , Bitte korrigiere mich wenn ich falsch liege. Wie ich schon oft sagte, fand ich magrittr Pipes sehr schön für die interaktive Verwendung, wenn ich Code-Stücke präsentieren möchte, aber nicht wirklich notwendig, wenn R-Pakete geschrieben werden, bei denen der Schwerpunkt auf Funktionalität liegt. IMO, wenn etwas vor Ort geändert werden kann, muss es einen anderen Operator haben als den, der nicht vor Ort geändert wird.

@franknarf1 ,

Erstens gab es keinen Anspruch, für ALLE R-Benutzer zu sprechen. Das ist eine lächerliche Behauptung. Der Hinweis auf "Erwartungen der Benutzer" bezog sich auf meine eigenen, vermutlich auf die OPs und mehrere meiner Schüler, die dt[ , var %<>% ... ] bereits ausprobiert haben und fragen, warum es nicht funktioniert hat. Darüber hinaus ist es gefährlich, Benutzer zu _zwingen_, "den Unterschied zu lernen, während sie lernen, data.table zu verwenden", wenn DT wie erwartet funktionieren kann. Dies führt zu einem schlechten Softwaredesign.

Zweitens ist es, wie Sie betonen, Sache des Einzelnen, Argumente zugunsten des Vorschlags des OP, der magriitr-Syntax zu folgen, zu akzeptieren oder abzulehnen. Es wurden einige Argumente dafür vorgebracht, warum dies von Vorteil wäre, aber nur wenige überzeugende Argumente, warum eine Alternative überlegen oder sogar vorteilhaft wäre. Da die Implementierung anders ist, scheint es ein kleines Argument zu geben, aber das ist ein eher schwaches Argument.

Zusätzlich,

  • Das %<>% könnte auch implementiert werden, um mehrere Argumente zu verarbeiten und wäre im Kontext immer noch sinnvoll, während die Erwartungen von OP und anderen eingehalten werden. Der Vorschlag des OP gab nicht wirklich an, ob er mehrere Argumente ändern wollte.
  • Ob Sie einen Teil oder das Ganze modifizieren, ist eine Sache – Sie modifizieren immer einen Teil einer Sache, dh eine Umgebung.
  • Das Handeln oder Unterlassen der Entwickler ist ein weiterer Ablenkungsmanöver und bezieht sich nicht auf die Vorzüge des Vorschlags / der Anfrage des OP. Dies ist ein eher dürftiges Argument der Autorität, das in keiner Weise wirklich eine Meinung abgegeben hat.

Wenn es Argumente für / gegen den Vorschlag des OP gibt, würde ich diese gerne hören. Aber das einzige was ich gehört habe ist "weil es anders ist". Vielleicht werden einige dies als gültig ansehen, aber abgewogen gegen den ursprünglichen Vorschlag des OP scheint die Alternative nicht besser zu sein.

Jeder, der jemals data.table hat, musste irgendwann einmal lernen, wie man := (wahrscheinlich sehr bald nach dem Start). Oh nein, gruselig! Warum ist es nicht <- oder = ?

Die Antwort darauf ist eines der ersten Dinge, die jemand über die Verwendung von data.table lernt. Es ist das Thema der zweiten Intro-Vignette .

%<>% vs. %<:>% (oder was auch immer es sein mag) ist genau der gleiche Unterschied. Die Antwort wird also von Matt hier abgedeckt:

http://stackoverflow.com/questions/7033106/why-has-data-table-defined-rather-than-overloading

@jangorecki

Erstens müssen die meisten Benutzer den Unterschied zwischen Nach-Referenz und Nach-Wert nicht kennen. Es ist keine Voraussetzung für die Verwendung von DT, dass Sie dies wissen. Vermutlich ist die DT-Syntax deshalb so nah an DF. @mattdowle hätte DT mit einer rein funktionalen Schnittstelle übersichtlich gestalten können. Er tat es nicht. Vermutlich war einer der Gründe, dass DT als Drop-In-Ersatz fungieren könnte.

In Bezug auf die set* Funktionen können diese durch Verweis angegeben werden, aber es ist merkwürdig zu bemerken, dass sie nicht set*ByRef was klarer gewesen wäre. Die Funktionen scheinen hauptsächlich dafür zu existieren, eine effiziente Operation durchzuführen, einen DF in einen DT umzuwandeln und einen Schlüssel zu setzen. Dass sie als Hinweis auf eine By-Reference-Operation verstanden werden können, scheint zweitrangig.

Was := angeht , erinnere ich mich, dass := anstelle von = . IIRC, er sagte, er könne = und := sei verfügbar. IIRC, er hätte lieber = .

WRT, der Standard in der R-Community – berüchtigt für seinen Mangel an Standards – magrittr ist so gut wie es nur geht: allgegenwärtig verwendet und diskutiert. Das OP schlägt vor, dass die Interoperabilität damit eine nette Funktion wäre. Ich stimme zu. Wenn Sie diesbezüglich Zweifel haben, sehen Sie sich die CRAN-Seite an . Entwickler verwenden magrittr in ihren eigenen Paketen. Darüber hinaus ist das Schreiben von Paketen nicht die Mehrheit der R-Benutzer. Aber das ist wirklich ein Exkurs vom Thema.

Das von Ihnen angebotene Argument fällt unter: "DT unterscheidet sich von magrittr, da die Zuweisung durch Referenz erfolgt, also ist die Syntax anders". Worauf die Antwort noch lautet: Die Umsetzung ist anders, stimmt. aber die Schnittstelle sollte die gleiche sein, da sie für die meisten Benutzer effektiv die gleichen Operationen ist, den Erwartungen des Benutzers entspricht und deren wahre Operation aus dem Kontext abgeleitet werden kann.

@mattdowle hätte DT mit einer rein funktionalen Schnittstelle übersichtlich gestalten können. Er tat es nicht.

Ich bin froh, dass er es nicht getan hat. Sich auf "rein funktional" zu beschränken bedeutet einfach, einige wichtige Funktionen wegzulassen, die der Benutzer jetzt verwenden kann, um schnelleren und speichereffizienteren Code zu schreiben. Ich habe Projekte ( zB Ankermodellierung ), deren Verwendung in einem "rein funktionalen" Rahmen grundsätzlich nicht praktikabel wäre.

@jangorecki
Ich bin völlig einverstanden. Aber wir beginnen, vom ursprünglichen Vorschlag über die Vorzüge von DT abzuschweifen.

@MichaelChirico

Danke, dass Sie ein Gefühl der Erleuchtung in die Diskussion eingebracht haben. Die Verweise weichen ein wenig vom ursprünglichen Vorschlag ab, aber sie helfen, die für den OP-Vorschlag sprechenden Punkte zu veranschaulichen, nämlich

  • Die Wahl der Operatoren ist willkürlich. Matt Dowle hat es vor := mehreren versucht. Er probierte zuerst die offensichtlichen Dinge aus, die eher dem Standard entsprochen hätten: <- , <<- , := war nur gestolpert, weil es verfügbar war und Alternativen für hässliche Syntax geschaffen wurden . Es war klar, dass er bestehende Operatoren der Definition eines neuen vorzog.
  • Der Benutzer weiß aus dem Kontext, dass die Zuweisung durch eine Referenzzuweisung erfolgt, aber es spielt keine Rolle, wie sie erfolgt.
  • Etc.

Erstens gab es keinen Anspruch, für ALLE R-Benutzer zu sprechen. Das ist eine lächerliche Behauptung. Der Hinweis auf "Erwartungen der Benutzer" bezog sich auf meine eigenen, vermutlich auf die OPs und einige meiner Schüler

Es ist ein kontraproduktives und ablenkendes rhetorisches Mittel, würde ich sagen, von "Benutzern" zu sprechen, wenn man wirklich nur sich selbst meint. Sie haben vielleicht auch bemerkt, dass das OP sagte: " %:>% sieht gut aus für mich."

Das Handeln oder Unterlassen der Entwickler ist ein weiterer Ablenkungsmanöver und bezieht sich nicht auf die Vorzüge des Vorschlags / der Anfrage des OP. Dies ist ein eher dürftiges Argument der Autorität, das in keiner Weise wirklich eine Meinung abgegeben hat.

Es ist kein Appell an die Autorität, da ich dort keinen Punkt behaupte. Es ist ein Appell an Sie, sich zu beruhigen. Dies wird möglicherweise nie umgesetzt, also können Sie die Aufregung nicht verschieben? Ich kann mir vorstellen, dass es eine triviale Angelegenheit sein wird, den Namen der Funktion nach der Implementierung zu ändern (falls dies jemals der Fall ist), und wir werden ein besseres Gespür dafür haben, welche genaue Funktionalität wir zu diesem Zeitpunkt betrachten.

Zu den sachlichen Argumenten:

  • Ich halte es für sehr unwahrscheinlich, dass magrittr jemals %<>% , um mehrere Objekte auf seinem LHS zu ändern, wie list(x, y) %<>% log , analog zu DT[, c("x", "y") := lappy(.SD, log), .SDcols = c("x","y")] .
  • In ähnlicher Weise ist Ihr erster Hinweis, den ich gesehen habe, dass %<>% könnte, um einen Teil eines Objekts wie x[ 2:4 ] %<>% log zu ändern, was analog zu DT[ 2:4, x := log(x) ] .

Ich freue mich darauf, Ihre FRs für diese Funktionen auf https://github.com/tidyverse/magrittr/issues zu sehen und hoffe, dass sie durchgehen, denn ich würde diese Funktionalität sicherlich verwenden.

@franknarf1 ,

Punkt genommen; Ich hatte übersehen, dass das OP sagte, dass "%:>% für mich gut aussieht."

Trotzdem ist es nicht nur ich. Das OP schlug zuerst die magrittr-Syntax vor. Vermutlich hielt er es für eine gute Idee, obwohl er später eine Alternative einräumte. Ich hatte es auch für eine gute Idee gehalten, das hat mich hierher gebracht und dies wurde von mehreren Studenten veranlasst, die es ausprobiert haben. Vermutlich gibt es noch andere. Dies als einsamen Standpunkt abzutun, ist sowieso nebensächlich.

Zweitens handelte es sich bei dem Argument tatsächlich um einen Appell an die Behörde. Es kann auch "ein Appell an mich sein, mich zu beruhigen", obwohl ich vollkommen ruhig bin. Auf jeden Fall scheint der Punkt nicht zum Thema zu gehören, er geht nicht auf die Vorzüge des OP-Vorschlags ein. Auch die Tatsache, dass die Umsetzung sehr unwahrscheinlich ist, scheint für die Vorzüge des Vorschlags nicht relevant zu sein.

Es muss weiter zugeben, dass Sie Recht haben. Es ist trivial, den Namen der Funktion nach der Implementierung zu ändern. Eine solche Änderung könnte und wird jedoch wahrscheinlich jeden Code zerstören, der entwickelt wird, der die Funktion verwendet. Es ist durchaus sinnvoll, vor der Implementierung Zeit mit Diskussionen über die Schnittstelle zu verbringen, anstatt die Benutzer später mit einer inkompatiblen Änderung zu belasten. Es ist unklar, welchen Zweck das Herunterfahren von Diskussionen hat.

Was die inhaltlichen Argumente betrifft, so scheinen sie eher für eine erweiterte Funktionalität von magrittr zu plädieren, als die vorgeschlagene %<>% Syntax anzusprechen. (Persönlich stimme ich Ihnen zu, dass die magrittr-Leute Ihre Vorschläge umsetzen sollten, insbesondere den ersten. Ich bin mir nicht sicher, ob ich den zweiten so oft verwenden würde.) Unabhängig von dem Vorschlag an die magrittr-Leute gibt es nichts inkonsequent von DT, Ihre Verbesserungen zu übernehmen und den Operator magrittr %<>% . Und ich muss noch wirklich ein überzeugendes Argument für die Überlegenheit von %:=% (oder einer Alternative) gegenüber %<>% lesen.

In dem Bemühen, zum Thema zurückzukehren, hielt ich es für sinnvoll, die relevanten Argumente zusammenzufassen.

Argument für %:>% :

  • dass eine DT-Pipe-Forward-Zuweisung die Zuweisung per Referenz implementiert. Dies ist bei den Operatoren zu unterscheiden, da es den Benutzern klar macht, wie die Zuordnung erfolgt. Dies kann unnötige Verwirrung vermeiden.
  • in manchen Fällen (zB Mehrfachbelegung, Teilbelegung) kann DT zusätzliche Funktionen hinzufügen, die von Magrittr (noch?) nicht unterstützt werden. Daher ist es am besten, zwischen den Operationen zu unterscheiden.
  • %<>% ist so willkürlich wie jede andere Wahl, %:>% ist eher DT-ähnlich.

Argumente für %<>% :

  • magrittr hat bereits einen Pipe-Forward-Assignment-Operator implementiert, er ist weit verbreitet und scheint so gut wie alles Standard zu sein. Die Befolgung eines Standards, wie implizit auch immer, bedeutet, dass der Aufwand für die DT-Entwickler in Bezug auf den Dokumentations- und Erklärungsaufwand reduziert wird, der zur Beschreibung des neuen Betreibers erforderlich ist.
  • Benutzer verwenden bereits magrittr mit DT im RHS von := . Darüber hinaus deuten einige Hinweise darauf hin, dass Benutzer die Syntax %<>% magrittr
  • Das Verschieben von Code nach dplyr/magrittr <--> DT wäre einfacher und einfacher, da die Syntax in einigen Fällen ähnlich sein kann.
  • Eine Erhöhung der Zahl der Operatoren führt zu zusätzlicher Komplexität. In diesem Fall ist die Komplexität unnötig, da Operatoren die Aktion spezifizieren sollten und notwendigerweise die Implementierung angeben müssen – so funktionieren generische Methoden.
  • %:>% ist so beliebig wie %<>% .

Das Verschieben von Code nach dplyr/magrittr <--> DT wäre einfacher und einfacher, da die Syntax in einigen Fällen ähnlich sein kann.

Sie vermissen absolut, wie eine Änderung durch Verweis diese Art von portiertem Code schrecklich zerstören würde.
Stellen, von denen Sie wussten, dass sich Ihr ursprüngliches Objekt nicht ändern wird, ändern sich plötzlich, weil sich die Zuweisungsmethode ändert. Aus diesem Grund ist es wirklich wichtig, die Operatoren zu unterscheiden (und die Möglichkeit der Zuweisung nach Wert (Kopieren) in derselben Zeile zu halten Code auch).

Das gleiche Problem wie beim Kopieren einer data.table vs. kopieren eines data.frame (dt2 <-dt), plötzlich kratzen Sie sich den Kopf darüber, warum Ihr ursprüngliches dt aktualisiert wurde, wenn Sie nur am zweiten gearbeitet haben.

Diese genaue Vorsichtsmaßnahme macht auch Ihren ersten Punkt ungültig, da er eine genaue Dokumentation dessen erfordert, was der Betreiber tut. Die Verwendung einer anderen erleichtert das Auffinden der richtigen Dokumentation.

@tensibai,

Verstanden. Somit ist das "kann sein" Teil der Behauptung.​

Am Mittwoch, den 2. November 2016 um 01:32 Uhr schrieb Tensibai [email protected] :

Das Verschieben von Code nach dplyr/magrittr <--> DT wäre einfacher und einfacher,
da die Syntax in einigen Fällen ähnlich sein kann.

Sie vermissen absolut, wie eine Änderung durch Verweis schrecklich wäre
brechen Sie diese Art von portiertem Code. Orte, an denen du dein Original gekannt hast
Objekt wird sich nicht ändern wird sich plötzlich ändern, weil die Zuweisungsmethode
ändern, deshalb ist es wirklich wichtig, die Operatoren zu unterscheiden
(und die Möglichkeit der Wertzuweisung (Kopie) in der gleichen Zeile zu halten
auch Code).

Das gleiche Problem wie beim Kopieren einer data.table vs. kopieren eines data.frame
(dt2 <- dt), plötzlich kratzt du dich am Kopf, warum dein Original dt hat
aktualisiert wurde, wenn Sie nur am zweiten gearbeitet haben.


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/Rdatatable/data.table/issues/1208#issuecomment -257801913,
oder den Thread stumm schalten
https://github.com/notifications/unsubscribe-auth/AC5xaxyWXkh4C7i5-GtjMFiQ0AY2L5BLks5q6EqIgaJpZM4FSJR5
.

Vielen Dank für alle Ihre Kommentare und Rückmeldungen.

Nur eine Kleinigkeit (vielleicht übersehe ich etwas): Macht es in diesem speziellen Fall überhaupt einen Unterschied, ob es sich um eine Zuweisung per Referenz oder per Wert handelt? Wir möchten eine Spalte (oder mehrere Spalten) in der data.table aktualisieren. Der Benutzer weiß, dass die alte Spalte so oder so überschrieben wird. Es gibt keinen Raum für Missverständnisse, oder? Im Gegensatz dazu ist dies ganz anders als DTa=DTb vs. DTa=copy(DTb) (über die ich in dieser Funktionsanfrage nicht spreche), wo wir uns mit der data.table selbst befassen und wo es macht einen Unterschied, ob wir nach Referenz oder nach Wert zuweisen.

@meine-R-Hilfe,

Deine Intuition ist richtig.

Es macht keinen Unterschied für den Benutzer machen , wie dieser Vorgang ist _implemented_. Aus Benutzersicht sind die Ergebnisse gleich – die Werte in der Spalte werden neu zugewiesen. Es gab einige Argumente, die besagten, dass es eine gewisse Differenzierung geben sollte, es gab keine überzeugende Erklärung für das _Warum_.

Ihr Vorschlag, die Syntax %<>% ist vernünftig. Es geht korrekterweise davon aus, dass sich die Implementierung von der _Schnittstelle_ unterscheidet, und da es eine weit verbreitete und bestehende Praxis zum Ausführen der Operation gibt, sollte sie übernommen werden. Dies folgt in der Tat guter Software-Design-Praxis.

( Als Randnotiz war ich ein wenig entmutigt, als Sie sagten: "Danke (SIC), %:>% sieht gut aus." danke für den Vorschlag. Es ist genial, ob es in DT implementiert ist oder nicht,)

Danke für deine Antwort, Christoph.

Nur um das klarzustellen, ich persönlich bevorzuge %<>% weil es eher mit magrittr übereinstimmt und viele Leute es zu verwenden scheinen. Wenn die data.table-Entwickler jedoch einen anderen Operator bevorzugen (zB %:>% ), kann ich auch damit leben (obwohl ich persönlich den magrittr-Weg bevorzuge).

Vielleicht hätte ich es so formulieren sollen. Entschuldigung, wenn es zu Verwirrung geführt hat.

Der Benutzer weiß, dass die alte Spalte so oder so überschrieben wird. Es gibt keinen Raum für Missverständnisse, oder?

Es macht für den Benutzer keinen Unterschied, wie dieser Vorgang implementiert wird. Aus Benutzersicht sind die Ergebnisse gleich – die Werte in der Spalte werden neu zugewiesen.

Ich habe immer noch das Gefühl, dass es Platz für Fußgeschütze mit Verbindungen gibt.

Wenn sich zwei Operatoren in Bezug auf ihre Nebenwirkungen ein wenig unterschiedlich verhalten, die gleich genannt werden, ist dies fehleranfällig und _wird_ zu Verwirrung führen. Ich kann nicht besser argumentieren, aber es gibt einen Grund dafür, warum R Sie warnt, wenn ein Paket eine Basisfunktion maskiert oder wenn ein Paket eine andere Paketfunktion überlädt.

Meiner Meinung nach macht es zumindest für einige Benutzer einen Unterschied, bestimmte Operatoren zu haben, wenn die Nebenwirkungen anders sind.

_Bonus_ Wenn Sie nach dem Operator suchen, landen Sie auf der DT-Seite, die seine Vorbehalte / Einschränkungen ohne Zweifel erklärt, anstatt zwei Möglichkeiten in der Hilfe zu haben.

Hier sprechen wir über eine Sprache, nicht über eine Benutzeroberfläche, während ich der Meinung bin, dass ein Software-Endbenutzer sich nicht um die Implementierung hinter der X-Schaltfläche kümmern sollte, stimme ich absolut nicht zu, dass sich ein Programmierer nicht um die Implementierung hinter einer Funktion kümmern sollte.

Der Haupteinwand ist: Jemand, der denkt, dass %<>% sich genauso verhält wie außerhalb eines DT, wird verrückt, wenn er seine DT-Spalten kratzt, wenn es nicht beabsichtigt ist.

TL;DR: Programmieren ist keine UX, Sie müssen genau wissen, was Sie wollen, daher sollte es nicht vorkommen, dass bekannte Namen wiederverwendet werden.

@Tensibai ,

Die Behauptung, die Nebenwirkungen seien irgendwie anders, ist fragwürdig. Es wird jeweils eine variable Neuzuordnung durchgeführt. Beides sind Nebenwirkungen. Die Implementierung (by-ref oder by-value) unterscheidet diese nicht wirklich, da sich die vergleichenden Endzustände beider Systeme auf analoge Weise geändert haben.

Auch wenn die Nebenwirkungen unterschiedlich sind. Die Unterscheidung ist eher unwichtig. Dieser Punkt wurde in der obigen Diskussion wiederholt angesprochen. Wenn die Unterscheidung wichtig wäre, sollte es möglich sein, ein Beispiel zu nennen, in dem sie für den Benutzer einen Unterschied machen würde. Das Fehlen eines kontrafaktischen Beispiels ist zwar nicht schlüssig, aber ein starkes Indiz dafür, dass es keine Unterscheidung gibt.

Gegenüber:

Sie müssen genau angeben, was Sie wollen, daher sollte es nicht vorkommen, dass bekannte Namen wiederverwendet werden.

Das ist einfach falsch. Die Wiederverwendung gängiger, bekannter Namen sollte nicht nur vorkommen, sondern ist sehr verbreitet und gilt als gute Programmierpraxis. Dies wird als Polymorphismus bezeichnet. Es ist durchaus akzeptabel, Methoden mit demselben Namen zu verwenden, die unterschiedlich implementiert sind:

person.sprechen()
"Hallo Welt"
Hund.sprechen()
"Schuss"

speak verwendet. Ist das eine schlechte Praxis? Nein. Tatsächlich wäre es eine Katastrophe, wenn der Polymorphismus nicht übernommen würde; jede Funktion und Methode hätte einen eigenen Namen. Obwohl dies ein ziemlich allgemeines Beispiel ist, das auf OO-Sprachen basiert, ist R nicht anders. R hat S3-Methoden und generische Funktionen, die auf ähnliche Weise funktionieren.

Der Vorschlag, dass:

Ich bin absolut nicht der Meinung, dass sich ein Programmierer nicht um die Implementierung einer Funktion kümmern sollte.

ist ähnlich fehlerhaft und widerspricht der Erfahrung der meisten Benutzer. Die meisten Programmierer verwenden wahrscheinlich Hunderte von Funktionen/Methoden. Sie tun dies, ohne ihre Implementierungsdetails zu kennen. Der Benutzer _muss_ die Eingabe und die Ausgabe/Nebenwirkungen kennen, damit die Funktionen nützlich sind, aber wie er dorthin gelangt, ist meistens irrelevant. Zugegeben, Benutzer müssen manchmal Details kennen, um die Funktion zu optimieren oder zu debuggen, aber es kann argumentiert werden, dass dies in den allermeisten Fällen der Fall ist. Stellen Sie sich die Welt vor, in der die Benutzer wissen mussten, wie jede einzelne Funktion auf allen Ebenen funktioniert. Die kognitive Belastung wäre immens; etwas Kompliziertes zu programmieren wäre eine unmögliche Aufgabe. Gegenüber:

Wenn Sie nach dem Operator suchen, landen Sie auf der DT-Seite, die seine Vorbehalte / Einschränkungen ohne Zweifel erklärt, anstatt zwei Möglichkeiten in der Hilfe zu haben.

Dies ist kein _Bonus_, sondern eine Haftung, indem a) Verwirrung stiftet (wie unterscheidet sich das von den sehr beliebten magrittr-Paketen, genau?) und b) zusätzliche unnötige Dokumentation überhaupt notwendig wird. Bei der magrittr-Syntax können DT-Entwickler sagen: "Gehen Sie dorthin und lesen Sie die Dokumente und die Vignette dort; DT unterstützt das, was sie dort tun." Diese Zusammenarbeit und paketübergreifende Kreditaufnahme erhöht den Wert von DT, magrittr und dem R-Ökosystem. )

Schließlich könnte aus den Kommentaren zu "Benutzeroberfläche", "X-Schaltfläche" und "UX" abgeleitet werden, dass eine bestimmte Benutzeroberfläche impliziert wurde. Das ist einfach nicht der Fall. Und obwohl es völlig klar ist, dass wir von einer Sprache sprechen, ist es falsch zu sagen, dass der Sprache eine Schnittstelle fehlt. Die Schnittstelle ist ihre Syntax und sie ist wichtig.

Zusammenfassend, damit das Problem schließlich gelöst werden kann.

Alles, was wir brauchen, ist die folgende Übersetzung.

DT[, a %<:>% fun] ## or "%:>%"

DT[, a := fun(a)]

Ist das richtig?

wie soll es sich verhalten, wenn a kein Symbol sondern eine Zeichenvariable ist?

DT[, "a" %<:>% fun]

DT[, "a" := fun(a)]   ## this?
DT[, "a" := fun("a")] ## or this?

Was ist, wenn seine Länge nicht 1 ist?

DT[, c("a","b") %<:>% fun]

DT[, c("a","b") %<:>% fun(a, b)]
DT[, c("a","b") %<:>% fun("a","b")]
DT[, c("a","b") %<:>% lapply(list(a, b), fun)]
DT[, c("a","b") %<:>% lapply(c("a", "b"), fun)]

Persönlich würde ich es schließen, da es nicht behoben wird, da es viel Komplexität hinzufügt und kein neues Problem löst.
Ich sehe darin Einigkeit, also schließen wir, wir können immer wieder öffnen, wenn es wirklich nötig ist.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen