Data.table: Integración con magrittr

Creado en 5 jul. 2015  ·  39Comentarios  ·  Fuente: Rdatatable/data.table

Esta es una solicitud de función que sigue a la discusión en la lista de correo .

Creo que sería útil tener algo como esto como forma abreviada:

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

Hasta ahora hay que escribir

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

o sin magrittr

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

Esto es particularmente importante si a se reemplaza con una variable que tiene un nombre largo, que luego es difícil de escribir y leer. Creo que hay ahorros significativos en la eficiencia (del programador) que se pueden lograr aquí, especialmente con nombres de variables más largos.

Comentario más útil

En resumen, para que el problema pueda resolverse eventualmente.

Todo lo que necesitamos es manejar la siguiente traducción.

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

DT[, a := fun(a)]

¿Está bien?

¿Cómo debería comportarse si a no es un símbolo sino una variable de carácter?

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

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

¿y si su longitud no es 1?

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)]

Personalmente, lo cerraría porque no se solucionará debido a que agrega mucha complejidad y no resuelve ningún problema nuevo.
Veo un acuerdo sobre eso, cerrando así, siempre podemos reabrir si realmente es necesario.

Todos 39 comentarios

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

Funciona perfectamente bien

Pero en mi humilde opinión

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

no está perfectamente bien. Me gusta la idea de agregar esta función de conveniencia.

¿Pero tal vez %:>% sería mejor que %<>% ?

No debería tener nombres tan extraños en su conjunto de datos. Es inconveniente y difícil de mantener. Aparte de eso, puede almacenar el nombre de la columna en alguna variable y luego hacer:

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

Tienes razón, pero incluso con variables que tienen una longitud intermedia, todavía encuentro la sintaxis magrittr mucho más conveniente para leer y escribir. De todos modos, esta es solo mi opinión personal.

Encuentro que a veces es mejor tener nombres de variables largos en conjuntos de datos complejos para dejar en claro lo que se guarda en una variable. Es una cuestión de preferencia personal. Por definición, las funciones de conveniencia no son necesarias para realizar una tarea, solo hacen que codificar sea más rápido y, a menudo, más fácil de entender. No tengo ninguna duda de que esta función sería de utilidad para muchos usuarios. Pero también entiendo que si los desarrolladores de data.table no quieren implementar / mantener (demasiadas) funciones de conveniencia, debe trazar la línea en alguna parte;)

Para aquellos de ustedes que están suscritos a este hilo, ignoren el último comentario (ahora eliminado). Fue una tontería.

Partiendo del comentario de @ and3k , veo algún valor de:

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

Creo que se lee mejor (es decir, := y %>% juntos). ¿Es una 'pipa feliz'? Soy un fanático de los esfuerzos para reducir la repetición de nombres de variables, como está escrito aquí: http://stackoverflow.com/a/10758086/403310

La parte => del operador :=> tiene un significado adicional, tal vez :=: ?

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

o :=. que se asigna directamente como := seguido de . pasado a diversión

¿Qué significado adicional tiene => ? El > es bueno porque transmite pasar el LHS como un argumento a RHS. Es por eso que Hadley cambió del %.% a %>% .

Tenía entendido que una parte importante de la motivación para pasar a %>% era que es mucho más fácil escribir que %.% (supongo que muchas veces tratando de escribir %.% daría como resultado accidentalmente %>% ).

Me refiero a operador _ mayor o igual_.
¿Y qué hay de %:>% ? Esto sería más fácil de escribir que %:=>% o %:=:% .
and3k ya menciono ese de arriba.

Mi voto es por %:>% o solo :> .

Los % solo están ahí porque R no permite operadores infijos en la naturaleza, ¿verdad? También podría mantener a los operadores dentro DT[] parsimonioso.

No había considerado el aspecto de mecanografía, es decir, mantener presionada la tecla Mayús para todos los caracteres en el operador es más fácil, supongo. Tiene sentido.
:> no analiza, lamentablemente. Lo que hay dentro de [...] todavía tiene que ser una sintaxis R válida (todos los argumentos se analizan siempre antes de pasar sin evaluar a la función) por lo que no podemos crear nuevos operadores dentro de [...] , todavía tenemos que ajustar con % .
Ok, entonces %:>% parece bien. No es una gran prioridad, pero no sería difícil de implementar y bueno haberlo debatido.

Gracias, %:>% parece bien.

Solo por curiosidad, ¿por qué :> no analiza mientras := analiza dentro de [....] ? := tampoco es válida la sintaxis R, ¿verdad?

@ my-R-help es una sintaxis válida, vea esto ¿Por qué: = se permite como un operador infijo?

+1 Estoy de acuerdo con la solicitud de la función OP y el uso de la sintaxis magrittr. Es la mejor opción y la más obvia por varias razones.

  • La gente ya está usando mucho DT con itmagrittr
  • La sintaxis de magrittr es omnipresente en este punto ... incluso podría tener su propia tecla de acceso rápido rstudio ... y cualquier otra opción sintáctica probablemente terminará en confusión.

Le recomiendo encarecidamente que no piense demasiado en este FR introduciendo un nuevo operador cuya elección sea igual de arbitraria que fue la elección de magrittr ...

Le recomiendo encarecidamente que no piense demasiado en este FR introduciendo un nuevo operador cuya elección sea igual de arbitraria que fue la elección de magrittr ...

@ctbrown La propuesta es para un operador de tubería que hace algo diferente al %>% vanilla de magrittr, un paquete que también tiene varios otros operadores de tubería. Siempre que no entre en conflicto con ninguno de ellos, ¿cuál es el problema?

Creo que la solicitud de FR del OP fue lo suficientemente clara, es decir
para usar específicamente %<>% como la combinación-tubería-directa-y-asignación
operador. Presumiblemente esto se debe a que magrittr ya define %<>% para
precisamente este propósito. Dado que magrittr parece ser la tubería dominante
implementación y mucha gente parece estar usando% <>%, mis estudiantes y
colegas entre ellos. No tiene sentido introducir otro
operador para exactamente el mismo propósito. Tiene mucho más sentido elegir un
sintaxis que se alinea con lo que la comunidad ha estado expuesta o ya ha
adoptado. Vea mi punto sobre la ubicuidad.

Déjame preguntarte, ¿qué esperas ganar al presentar a otro operador?
que realiza exactamente la misma función en un contexto diferente? No puedo ver
cualquier beneficio. Cualquier operador que elija será tan arbitrario como el de magrittr.
Entonces, ¿no tiene sentido hacer que todo el sistema sea menos arbitrario simplemente
siguiendo el ejemplo de magrittr aquí en lugar de hacer otra arbitraria
decisión sintáctica?

El jueves 27 de octubre de 2016 a las 11:41 a. M., Franknarf1 [email protected]
escribió:

Te recomiendo encarecidamente que no pienses demasiado en este FR introduciendo un nuevo
operador cuya elección es igual de arbitraria que fue la elección de magrittr ..

@ctbrown https://github.com/ctbrown La propuesta es para un operador de tubería
que hace algo diferente al vainilla%>% de magrittr, un
paquete que también tiene varios otros operadores de tubería. Mientras no lo haga
conflicto con alguno de ellos, ¿cuál es el problema?

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/Rdatatable/data.table/issues/1208#issuecomment -256732710,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AC5xaxIp36dTUCz9d5a5mU7CJUV6PaxCks5q4PBDgaJpZM4FSJR5
.

¿ %<>% asigna por referencia? Si no es así, de hecho, no están haciendo exactamente lo mismo.

Técnicamente tienes razón, el% <>% de magrittr no asigna por referencia,
pero esto no viene al caso. Dentro de las expectativas de los usuarios, no hay
diferencia. La asignación, ya sea por referencia o por valor, es una
problema de implementación, no de interfaz. El PO ha sugerido adoptado
magrittr y no sugirió necesariamente la implementación.
Vi el mérito en la sugerencia de OP. Vea las razones anteriores. no
ver el fundamento de adoptar algo como '%:>% or anything as arbitrary. The merit of this has not been articulated. The % <>% `
El operador ya existe y es promovido activamente por magrittr (el duodécimo más
paquete popular de acuerdo con METACRAN).
ser el estándar (dentro de la comunidad R). Lo bueno de seguir
La práctica establecida es reducir la confusión del usuario y la necesidad de
documentación completa. Obtienes: "Oh, esto es lo mismo que magrittr, yo
conoce esta tubería hacia adelante y hace una asignación ", en lugar de" ¿qué es esto?
extraño%:>%? ¿Es un nuevo emoticón de payaso? "

El jueves 27 de octubre de 2016 a las 2:18 p.m., Michael Chirico [email protected]
escribió:

¿% <>% Asigna por referencia? Si no es así, de hecho _no_ están haciendo
exactamente lo mismo.

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/Rdatatable/data.table/issues/1208#issuecomment -256772769,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AC5xa3ssE14PcamL2U9HlvCdfA8-7Iz8ks5q4RUagaJpZM4FSJR5
.

Dentro de las expectativas de los usuarios, no hay diferencia.

Primero, no creo que sea cierto y que usted habla por todos los usuarios; Soy un usuario, por ejemplo. En segundo lugar, si es cierto, estos usuarios deberían conocer la diferencia a medida que aprenden a utilizar data.table.

Tus "razones de arriba" no se sostienen conmigo. De alguna manera no va en contra de magrittr implementar un operador de tubería que no se superponga para hacer algo distinto pero relacionado. Para mí, y esta es solo mi impresión, tanto como todo lo que has estado diciendo es tuyo, esto parece perfectamente consistente con la "práctica establecida" de magrittr (que uso casi tan a menudo como data.table ).

Es perfectamente posible que el uso en este contexto se asigne a varios objetos (columnas) a la vez, lo que seguramente estaría de acuerdo en que es bastante distinto de %<>% ..? quiero decir

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

Y, además de modificar por referencia y potencialmente modificar varias cosas a la vez, tenemos el hecho de que estamos modificando parte de una cosa (data.table), que es bastante diferente de %<>% .

De todos modos, dado que los desarrolladores no han mostrado ningún signo de hacer esta tarea en el corto plazo (al marcar este FR con una prioridad o un hito), ¿qué tal volver a visitar esto si realmente avanza?

@ctbrown _by-reference_ no solo es diferente en implementación, y debe diferenciarse de las funciones _by-value_ en la interfaz de usuario. Ese es el punto entero de set* funciones y := operador en data.table, para comunicar con claridad a los usuarios lo que realmente está modificando la entrada de una función. Es difícil juzgar sobre un estándar dentro de la comunidad R después de tan poco tiempo, las aplicaciones R se están escribiendo durante décadas y es demasiado pronto para juzgar sobre un "nuevo estándar", que al final es un AFAIK sobre el formato de código (anidamiento / anidación) , Por favor corrígeme si estoy equivocado. Como dije muchas veces antes, encontré las tuberías magrittr realmente agradables para uso interactivo cuando quiero presentar un fragmento de código, pero no es realmente necesario al escribir paquetes R donde el enfoque principal es la funcionalidad. En mi opinión, si algo se puede modificar en el lugar, debe tener un operador diferente al que no se modificará en el lugar.

@ franknarf1 ,

Primero, no hubo ningún reclamo en cuanto a hablar en nombre de TODOS los usuarios de R. Esa es una afirmación ridícula. La referencia a las "expectativas de los usuarios" fue para las mías, presumiblemente las OP y varios de mis estudiantes que ya han probado dt[ , var %<>% ... ] y me preguntan por qué no funcionó. Además, _Forzar_ a los usuarios a "aprender acerca de la diferencia a medida que aprenden a usar data.table" es peligroso si DT puede funcionar como cabría esperar. Esto conduce a un mal diseño de software.

En segundo lugar, como usted señala, depende del individuo aceptar o rechazar argumentos a favor de seguir la sugerencia del OP de seguir la sintaxis magriitr. Se han ofrecido algunos argumentos sobre por qué esto sería beneficioso, pero pocos argumentos convincentes ofrecieron por qué una alternativa sería superior o incluso beneficiosa. Parece haber un argumento menor porque la implementación es diferente, pero ese es un argumento bastante débil.

Adicionalmente,

  • El %<>% también podría implementarse para manejar múltiples argumentos y aún tendría perfecto sentido dentro del contexto mientras se adhiere a las expectativas de OP y de otros. La sugerencia del OP no especificó realmente si quería modificar múltiples argumentos.
  • Ya sea que modifique una parte o un todo, es una metedura de pata: siempre está modificando parte de una cosa, es decir, un entorno.
  • La acción o inacción de los desarrolladores es otra pista falsa y no se relaciona con los méritos de la propuesta / solicitud del OP. Este es un argumento de apelación a la autoridad bastante pobre que realmente no ha ofrecido una opinión de ninguna manera.

Si hay argumentos a favor / en contra de la sugerencia del OP, me encantaría escucharlos. Pero lo único que he escuchado es eso, "porque es diferente". Quizás algunos vean esto como válido, pero comparado con la sugerencia original de OP, la alternativa no parece mejor.

Todos los que alguna vez han usado data.table han tenido que aprender en algún momento u otro sobre el uso de := (probablemente muy poco después de comenzar). ¡Oh no, espeluznante! ¿Por qué no es <- o = ?

La respuesta a esto es una de las primeras cosas que alguien aprende sobre el uso de data.table . Es el tema de la segunda viñeta de introducción .

%<>% vs. %<:>% (o lo que sea que termine siendo) es exactamente la misma distinción. Entonces, Matt cubre la respuesta aquí:

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

@jangorecki

Primero, la mayoría de los usuarios no necesitan saber distinguir la diferencia entre por referencia y por valor. No es un requisito previo para usar DT que lo sepa. Presumiblemente, esta es la razón por la que la sintaxis DT es tan cercana a DF. @mattdowle podría haber diseñado claramente DT con una interfaz puramente funcional. No lo hizo. Presumiblemente, una de las razones fue que DT podría funcionar como un reemplazo directo.

Con respecto a las funciones set* , estas pueden indicar por referencia, pero es curioso notar que no fueron nombradas set*ByRef cual hubiera sido más claro. Las funciones parecen existir principalmente para realizar una operación eficiente, convertir un DF en DT y configurar una clave. Parece secundario que puedan tomarse para indicar una operación por referencia.

En cuanto a := , creo que recuerdo ser @mattdowle preguntó en UCLA usuario ¿Por qué se usa := en lugar de = . IIRC, dijo que no podía usar = y que := estaba disponible. IIRC, hubiera preferido usar = .

WRT, el estándar en la comunidad R, conocido por su falta de estándares, magrittr es tan bueno como es posible: se usa y se discute de manera ubicua. El OP sugiere que la interoperabilidad sería una buena característica. Estoy de acuerdo. Si tienes alguna duda al respecto, echa un vistazo a su página CRAN . Los desarrolladores están usando magrittr en sus propios paquetes. Además, la escritura de paquetes no es la mayoría de los usuarios de R. Pero esto es realmente una digresión del tema.

El argumento que ofrece se incluye en: "DT es diferente de magrittr ya que la asignación es por referencia, por lo que la sintaxis es diferente". A lo que la respuesta sigue siendo: La implementación es diferente, cierto. pero la interfaz debe ser la misma ya que efectivamente es la misma operación para la mayoría de los usuarios, se ajusta a las expectativas del usuario y cuya verdadera operación puede inferirse del contexto.

@mattdowle podría haber diseñado claramente DT con una interfaz puramente funcional. No lo hizo.

Me alegro de que no lo hiciera. Bloquear en "puramente funcional" simplemente se traduce en eliminar algunas características importantes que el usuario ahora puede usar para escribir código más rápido y más eficiente en memoria. Tengo proyectos (es decir, modelos de anclaje ) que básicamente serían imprácticos de usar en un marco "puramente funcional".

@jangorecki
Estoy totalmente de acuerdo. Pero estamos empezando a desviarnos de la propuesta original a los méritos de DT.

@MichaelChirico

Gracias por aportar un sentido de iluminación a la discusión. Las referencias se desvían un poco de la propuesta original, pero ayudan a ilustrar los puntos a favor de la propuesta de OP, a saber,

  • La elección de operadores es arbitraria. Matt Dowle probó varios antes de := . Primero probó las cosas obvias que se habrían alineado más con el estándar primero: <- , <<- , := simplemente se topó porque estaba disponible y se hicieron alternativas para una sintaxis desagradable . Estaba claro que prefería los operadores existentes a definir uno nuevo.
  • El usuario sabrá, por el contexto, que la asignación se produce por asignación de referencia, pero no importa cómo se produzca.
  • Etc.

Primero, no hubo ningún reclamo en cuanto a hablar en nombre de TODOS los usuarios de R. Esa es una afirmación ridícula. La referencia a las "expectativas de los usuarios" era la mía, presumiblemente los OP y varios de mis estudiantes.

Es un recurso retórico contraproducente y distractor, yo diría, para referirse a "usuarios" cuando en realidad solo te refieres a ti mismo. También puede haber notado que el OP decía " %:>% parece bien".

La acción o inacción de los desarrolladores es otra pista falsa y no se relaciona con los méritos de la propuesta / solicitud del OP. Este es un argumento de apelación a la autoridad bastante pobre que realmente no ha ofrecido una opinión de ninguna manera.

No es una apelación a la autoridad ya que no estoy discutiendo un punto allí. Es un llamado a que se calme. Es posible que esto nunca se implemente, así que ¿no puede aplazar el alboroto? Me imagino que será una cuestión trivial cambiar el nombre de la función después de que se implemente (si es que alguna vez se implementa), y tendremos una mejor idea de qué funcionalidad exacta estamos viendo en ese momento.

En cuanto a los argumentos sustantivos:

  • Creo que es muy poco probable que magrittr alguna vez use %<>% para modificar varios objetos en su LHS, como list(x, y) %<>% log , análogo a DT[, c("x", "y") := lappy(.SD, log), .SDcols = c("x","y")] .
  • De manera similar, la suya es la primera pista que he visto de que %<>% podría usarse para modificar parte de un objeto como x[ 2:4 ] %<>% log , que es análogo a DT[ 2:4, x := log(x) ] .

Espero ver sus FR para estas funciones en https://github.com/tidyverse/magrittr/issues y espero que se cumplan, porque ciertamente usaría esa funcionalidad.

@ franknarf1 ,

Punto a favor; Me había perdido que el OP decía que "%:>% me parece bien".

No obstante, no soy solo yo. El OP sugirió primero la sintaxis magrittr, primero. Presumiblemente, pensó que era una buena idea a pesar de ceder a una alternativa más tarde. También me había parecido una buena idea, eso es lo que me trajo aquí y esto fue impulsado por varios estudiantes que lo han probado. Presumiblemente, hay otros. De todos modos, descartar esto como un punto de vista solitario no viene al caso.

En segundo lugar, el argumento fue, de hecho, una apelación a la autoridad. También puede ser "un llamado a que me calme", ​​aunque estoy perfectamente tranquilo. En cualquier caso, el punto parece fuera de tema, no aborda los méritos de la sugerencia del OP. Además, el hecho de que sea muy poco probable que esto se aplique no parece ser relevante para los méritos de la propuesta.

Además, debe admitir que está en lo cierto. Será trivial cambiar el nombre de la función una vez implementada. Sin embargo, dicho cambio podría y probablemente romperá cualquier código desarrollado que utilice la función. Tiene mucho sentido dedicar tiempo a discutir la interfaz antes de implementar en lugar de sobrecargar a los usuarios con un cambio incompatible más adelante. No está claro para qué sirve el cierre de la discusión para un propósito útil.

En cuanto a los argumentos sustantivos, parecen abogar más por una mayor funcionalidad de magrittr que la sintaxis propuesta %<>% . (En una nota personal, estoy de acuerdo con usted en que la gente de magrittr debería implementar sus sugerencias, especialmente la primera. No estoy seguro de si usaría tanto la segunda). Independientemente de la propuesta a la gente de magrittr, no hay nada inconsistente de DT al adoptar sus mejoras y usar el operador magrittr %<>% . Y todavía tengo que leer realmente un argumento convincente de la superioridad de %:=% (o una alternativa) a %<>% .

En un esfuerzo por volver al tema, pensé que podría ser útil resumir los argumentos relevantes.

Argumento a favor de %:>% :

  • que una asignación DT pipe-forward implementará la asignación por referencia. Esto debe distinguirse en los operadores, ya que deja claro a los usuarios cómo se implementa la asignación. Esto puede evitar confusiones innecesarias.
  • Puede haber algunos casos (por ejemplo, asignación múltiple, asignación parcial) en los que DT puede agregar características adicionales que no son (¿todavía?) compatibles con magrittr. En consecuencia, es mejor distinguir entre las operaciones.
  • %<>% es tan arbitrario como cualquier otra opción, %:>% es más parecido a DT.

Argumentos a favor de %<>% :

  • magrittr ya ha implementado operadores de asignación de tubería hacia adelante, se usa ampliamente y parece ser un estándar. Seguir un estándar, aunque sea implícito, significa que las cargas de los desarrolladores de DT se reducen en la cantidad de documentación y explicación necesaria para describir al nuevo operador.
  • Los usuarios ya usan magrittr con DT en el RHS de := . Además, alguna evidencia sugiere que los usuarios esperan / han probado la sintaxis magrittr %<>% . Adoptarlo se ajustaría a las expectativas de estos usuarios.
  • Mover el código hacia-desde dplyr / magrittr <--> DT sería más simple y fácil, ya que en algunos casos la sintaxis puede ser similar.
  • Un aumento en el número de operadores conduce a una complejidad adicional. En este caso, la complejidad es innecesaria, ya que los operadores deben especificar la acción y necesariamente deben especificar la implementación; así es como funcionan los métodos genéricos.
  • %:>% es tan arbitrario como %<>% .

Mover el código hacia-desde dplyr / magrittr <--> DT sería más simple y fácil, ya que en algunos casos la sintaxis puede ser similar.

Te estás perdiendo por completo cómo una modificación por referencia rompería terriblemente este tipo de código portado.
Los lugares en los que sabía que su objeto original no cambiaría cambiarán repentinamente porque el método de asignación cambia, por eso es realmente importante distinguir los operadores (y mantener la posibilidad de asignar por valor (copia) en la misma línea de código también).

Ese es el mismo problema que cuando copia un data.table en lugar de copiar un data.frame (dt2 <- dt), de repente se rasca la cabeza acerca de por qué su dt original se ha actualizado cuando trabajó solo en el segundo.

Esta precaución exacta a tomar, invalida también su primer punto, ya que requiere una documentación precisa de lo que hace el operador, usar una diferente facilitará la búsqueda de la documentación correcta.

@tensibai,

Comprendido. Por tanto, el "puede ser" parte de la afirmación.

El miércoles 2 de noviembre de 2016 a la 1:32 a. M., Tensibai [email protected] escribió:

Mover el código de dplyr / magrittr <--> DT sería más simple y fácil,
ya que en algunos casos la sintaxis puede ser similar.

Te estás perdiendo por completo cómo una modificación por referencia sería terriblemente
romper este tipo de código portado. Lugares donde conociste tu original
el objeto no cambiará cambiará repentinamente porque el método de asignación
cambiar, esta es realmente la razón por la que es importante distinguir los operadores
(y mantener la posibilidad de asignar por valor (copiar) en la misma línea
de código también).

Ese es el mismo problema que cuando copia un data.table vs copia un data.frame
(dt2 <- dt), de repente te rascas la cabeza sobre por qué tu dt original tiene
se actualizó cuando trabajó solo en el segundo.

-
Recibes esto porque te mencionaron.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/Rdatatable/data.table/issues/1208#issuecomment -257801913,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AC5xaxyWXkh4C7i5-GtjMFiQ0AY2L5BLks5q6EqIgaJpZM4FSJR5
.

Gracias por todos sus comentarios y sugerencias.

Solo una cosa menor (tal vez me falta algo): ¿En este caso específico, incluso hace una diferencia si se asigna por referencia o por valor? Lo que queremos hacer es actualizar una columna (o varias columnas) dentro del data.table. El usuario sabe que la columna anterior se sobrescribirá de cualquier manera. No hay lugar para malentendidos, ¿verdad? Por el contrario, esto es muy diferente a DTa=DTb frente a DTa=copy(DTb) (de lo que no estoy hablando en esta solicitud de función), donde estamos tratando con la tabla de datos en sí, y donde hace una diferencia si asignamos por referencia o por valor.

@ my-R-help,

Tu intuición es correcta.

No hace una diferencia para el usuario como esta operación es _implemented_. Desde la perspectiva de los usuarios, los resultados son los mismos: los valores de la columna se reasignan. Ha habido algunos argumentos que afirman que debería haber alguna diferenciación, no ha habido una explicación convincente en cuanto a _por qué_.

Su propuesta de adoptar la sintaxis %<>% es sensata. Asume correctamente que la implementación es distinta de la _interfaz_ y dado que existe una práctica popular y existente para realizar la operación, debe adoptarse. Esto, de hecho, sigue las buenas prácticas de diseño de software.

(Como nota al margen, me sentí un poco desanimado cuando dijiste: "Gracias (SIC),%:>% me parece bien", y no defendiste con más fuerza tu intuición inicial y tu propuesta con más fuerza. En cualquier caso, gracias por la propuesta. Es genial si se implementa en DT o no,)

Gracias por tu respuesta, Christopher.

Solo para aclarar, personalmente tengo una preferencia por %<>% porque es más consistente con magrittr y parece que mucha gente lo está usando. Sin embargo, si los desarrolladores de data.table prefieren otro operador (por ejemplo, %:>% ), también puedo vivir con eso (aunque personalmente prefiero la forma magrittr).

Quizás debería haberlo expresado de esa manera. Lo siento si causó alguna confusión.

El usuario sabe que la columna anterior se sobrescribirá de cualquier manera. No hay lugar para malentendidos, ¿verdad?

No supone ninguna diferencia para el usuario cómo se implementa esta operación. Desde la perspectiva de los usuarios, los resultados son los mismos: los valores de la columna se reasignan.

Todavía siento que hay espacio para pistolas con juntas.

Tener dos operadores que se comporten de manera un poco diferente en sus efectos secundarios con el mismo nombre es propenso a errores y _conducirá a confusión. No puedo argumentar mejor que eso, pero hay una razón por la que R le advierte cuando un paquete enmascara una función base o cuando se carga un paquete sobrecarga otra función del paquete.

En mi opinión, hace una diferencia para al menos algunos usuarios tener operadores específicos cuando los efectos secundarios serán diferentes.

_Bonus_ buscando el operador, terminará en la página de DT explicando sus advertencias / limitaciones sin duda en lugar de tener dos opciones en la ayuda.

Aquí estamos hablando de un lenguaje, no de una interfaz de usuario, mientras que estoy de acuerdo en que un usuario final de software no debería preocuparse por la implementación detrás del botón X, estoy muy en desacuerdo que un programador no debería preocuparse por la implementación detrás de una función.

La principal objeción es: alguien que piense que %<>% se comportará igual que fuera de un DT se volverá loco cuando raye sus columnas de DT cuando no esté previsto.

TL; DR: La programación no es una UX, debe ser específico sobre lo que desea, por lo tanto, no debería suceder la reutilización de nombres conocidos.

@Tensibai ,

La afirmación de que los efectos secundarios son de alguna manera diferentes es dudosa. En cada caso, se está realizando una reasignación de variable. Ambos son efectos secundarios. La implementación (por referencia o por valor) no los distingue realmente, ya que los estados finales comparativos de ambos sistemas han cambiado de manera análoga.

Incluso si los efectos secundarios son diferentes. La distinción carece de importancia. Este punto se ha planteado repetidamente en la discusión anterior. Si la distinción fuera importante, debería ser posible proporcionar un ejemplo en el que marcaría una diferencia para el usuario. La falta de un ejemplo contra los hechos, aunque no sea concluyente, es una fuerte indicación de que no hay distinción.

Con respecto a:

tienes que ser específico sobre lo que quieres, por lo tanto, no debería suceder la reutilización de nombres conocidos.

Esto es simplemente incorrecto. La reutilización de nombres comunes y conocidos no solo debería ocurrir, es muy común y se considera una buena práctica de programación. A esto se le llama polimorfismo. Es perfectamente aceptable tener métodos con el mismo nombre que se implementen de manera diferente:

person.speak ()
"Hola Mundo"
dog.speak ()
"guau"

En cada caso se utilizó speak . ¿Es esta una mala práctica? No. De hecho, si no se adopta el polimorfismo sería un desastre; cada función y método tendría su propio nombre. Si bien este es un ejemplo bastante genérico basado en lenguajes OO, R no es diferente. R tiene métodos S3 y funciones genéricas que funcionan de manera similar.

La sugerencia de que:

Estoy muy en desacuerdo que un programador no debería preocuparse por la implementación detrás de una función.

es igualmente defectuoso y es contrario a la experiencia de la mayoría de los usuarios. La mayoría de los programadores probablemente usan cientos de funciones / métodos. Lo hacen sin conocer los detalles de su implementación. El usuario _si_ necesita conocer la entrada y la salida / efectos secundarios para que las funciones sean útiles, pero la forma en que llega allí suele ser irrelevante. Por supuesto, los usuarios a veces necesitan conocer detalles para modificar o depurar la función, pero se puede argumentar que esto ocurre en la gran minoría de los casos. Considere el mundo donde los usuarios tenían que saber cómo funcionaban todas y cada una de las funciones en todos los niveles. La carga cognitiva sería inmensa; programar cualquier cosa de complejidad sería una tarea imposible. Con respecto a:

Al buscar un operador adicional, terminará en la página de DT explicando sus advertencias / limitaciones sin duda en lugar de tener dos opciones en la ayuda.

Esto no es un _Bonus_, sino una desventaja al a) introducir confusión (¿en qué se diferencia exactamente de los muy populares paquetes magrittr, exactamente?) Y b) crear la necesidad de documentación adicional innecesaria en primer lugar. Si la sintaxis magrittr, los desarrolladores de DT pueden decir: "ve allí y lee los documentos y la viñeta; DT admite lo que están haciendo allí". Esta cooperación y el préstamo de paquetes cruzados aumentan el valor de DT, magrittr y el ecosistema R. )

Por último, se podría inferir que de los comentarios sobre "interfaz de usuario", "botón X" y "UX", había una interfaz de usuario específica implícita. Ese simplemente no es el caso. Y, si bien está muy claro que estamos hablando de un idioma, es erróneo decir que el idioma carece de interfaz. La interfaz es su sintaxis y es importante.

En resumen, para que el problema pueda resolverse eventualmente.

Todo lo que necesitamos es manejar la siguiente traducción.

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

DT[, a := fun(a)]

¿Está bien?

¿Cómo debería comportarse si a no es un símbolo sino una variable de carácter?

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

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

¿y si su longitud no es 1?

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)]

Personalmente, lo cerraría porque no se solucionará debido a que agrega mucha complejidad y no resuelve ningún problema nuevo.
Veo un acuerdo sobre eso, cerrando así, siempre podemos reabrir si realmente es necesario.

¿Fue útil esta página
0 / 5 - 0 calificaciones