.SD
parece útil pero realmente no sé qué estoy haciendo con él. Que significa? ¿Por qué hay un período anterior (punto final)? ¿Qué sucede cuando lo uso?
Leí:
.SD
es un que data.table
contiene el subconjunto de x
datos de cada grupo, excluyendo las columnas del grupo. Se puede usar al agrupar por i
, al agrupar por by
, con clave by
y _ad hoc_by
¿Eso significa que la hija data.table
se guarda en la memoria para la próxima operación?
r
data.table
Farrel
fuente
fuente
?data.table
fue mejorado en v1.7.10, gracias a esta pregunta. Ahora explica el nombre.SD
según la respuesta aceptada.Respuestas:
.SD
significa algo como "S
ubset ofD
ata.table". La inicial no tiene importancia"."
, excepto que hace que sea aún más improbable que haya un choque con un nombre de columna definido por el usuario.Si este es su data.table:
Hacer esto puede ayudarlo a ver qué
.SD
es:Básicamente, la
by=y
declaración divide la tabla de datos original en estos dos sub-data.tables
y opera en ellos a su vez.
Mientras está operando en cualquiera de los dos, le permite referirse al subtítulo actual
data.table
utilizando el apodo / identificador / símbolo.SD
. Eso es muy útil, ya que puede acceder y operar en las columnas como si estuviera sentado en la línea de comando trabajando con una sola tabla de datos llamada.SD
... excepto que aquí,data.table
llevará a cabo esas operaciones en cada uno de los subdefinidosdata.table
por combinaciones de la clave, "pegarlas" de nuevo juntas y devolver los resultados en un solodata.table
!fuente
.SD
esDT[,print(.SD),by=y]
.DT[,print(.SD[,y]),by=y]
, indica que tengo acceso al valor dey
, aunque no sea parte de.SD
. ¿De dónde es el valor dey
ser explorado? ¿Está disponible b / c es el valor actual deby
?.SD[,y]
es undata.table
subconjunto regular, yay
que no se ve una columna.SD
en el entorno que lo llamó, que en este caso es elj
entorno (de laDT
consulta) dondeby
están disponibles las variables. Si no se encuentra allí, se ve en el padre, y en su padre, etc., de la forma habitual de R. (Bueno, también a través del alcance heredado de unión, que no se usa en estos ejemplos porque no hayi
s).by=list(x,y,z)
significaríax
,y
yz
están disponibles paraj
. Para acceso genérico también están envueltos.BY
. La pregunta frecuente 2.10 tiene algo de historia, pero podría agregarse algo de claridad?data.table
. Genial, la ayuda documental sería muy bienvenida. Aún mejor si desea unirse al proyecto y cambiar directamente.Editar:
Dado lo bien recibida que fue esta respuesta, la he convertido en una viñeta de paquete ahora disponible aquí
Dada la frecuencia con la que esto ocurre, creo que esto justifica un poco más de exposición, más allá de la útil respuesta dada por Josh O'Brien arriba.
Además del S ubset del acrónimo D ata generalmente citado / creado por Josh, creo que también es útil considerar que la "S" significa "Selfsame" o "Self-reference" -
.SD
es en su forma más básica un referencia reflexiva adata.table
sí mismo: como veremos en los ejemplos a continuación, esto es particularmente útil para encadenar "consultas" (extracciones / subconjuntos / etc. usando[
). En particular, esto también significa que.SD
es en sí undata.table
(con la advertencia de que no permite la asignación con:=
).El uso más simple de
.SD
es para subconjuntos de columnas (es decir, cuándo.SDcols
se especifica); Creo que esta versión es mucho más sencilla de entender, por lo que cubriremos eso primero a continuación. La interpretación de.SD
en su segundo uso, los escenarios de agrupación (es decir, cuándoby =
okeyby =
se especifica), es ligeramente diferente, conceptualmente (aunque en el fondo es lo mismo, ya que, después de todo, una operación no agrupada es un caso extremo de agrupación con solo un grupo).Aquí hay algunos ejemplos ilustrativos y algunos otros ejemplos de usos que yo mismo implemento a menudo:
Cargando datos de Lahman
Para darle a esto una sensación más real, en lugar de inventar datos, carguemos algunos conjuntos de datos sobre el béisbol de
Lahman
:Desnudo
.SD
Para ilustrar lo que quiero decir sobre la naturaleza reflexiva de
.SD
, considere su uso más banal:Es decir, acabamos de regresar
Pitching
, es decir, esta era una forma excesivamente detallada de escribirPitching
oPitching[]
:En términos de subconjunto,
.SD
sigue siendo un subconjunto de los datos, es solo trivial (el conjunto en sí).Subconjunto de columnas:
.SDcols
La primera forma de afectar lo que
.SD
es es limitar las columnas contenidas en el.SD
uso del.SDcols
argumento para[
:Esto es solo para ilustración y fue bastante aburrido. Pero incluso este simple uso se presta a una amplia variedad de operaciones de manipulación de datos altamente beneficiosas / ubicuas:
Conversión de tipo de columna
La conversión del tipo de columna es una realidad para la mezcla de datos: a partir de este escrito,
fwrite
no se puede leer automáticamenteDate
oPOSIXct
columnas , y las conversiones de ida y vuelta entrecharacter
/factor
/numeric
son comunes. Podemos usar.SD
y.SDcols
convertir por lotes grupos de tales columnas.Notamos que las siguientes columnas se almacenan como
character
en elTeams
conjunto de datos:Si está confundido por el uso de
sapply
aquí, tenga en cuenta que es lo mismo que para la base Rdata.frames
:La clave para comprender esta sintaxis es recordar que a
data.table
(así como adata.frame
) se puede considerar como un lugarlist
donde cada elemento es una columna; por lo tanto,sapply
/ selapply
aplicaFUN
a cada columna y devuelve el resultado comosapply
/lapply
normalmente lo haría (aquí,FUN == is.character
devuelve unlogical
de longitud 1, entoncessapply
devuelve un vector).La sintaxis para convertir estas columnas
factor
es muy similar: simplemente agregue el:=
operador de asignaciónTenga en cuenta que debemos incluir
fkt
paréntesis()
para forzar a R a interpretar esto como nombres de columna, en lugar de intentar asignar el nombrefkt
al RHS.La flexibilidad de
.SDcols
(y:=
) para aceptar uncharacter
vector o uninteger
vector de posiciones de columna también puede ser útil para la conversión basada en patrones de nombres de columna *. Podríamos convertir todas lasfactor
columnas acharacter
:Y luego convierta todas las columnas que contienen de
team
nuevo afactor
:** El uso explícito de números de columna (como
DT[ , (1) := rnorm(.N)]
) es una mala práctica y puede conducir a un código silenciosamente dañado con el tiempo si cambian las posiciones de las columnas. Incluso el uso implícito de números puede ser peligroso si no mantenemos un control inteligente / estricto sobre el orden de cuándo creamos el índice numerado y cuándo lo usamos.Control de RHS de un modelo
La especificación del modelo variable es una característica central del análisis estadístico robusto. Tratemos de predecir la ERA de un lanzador (Promedio de carreras ganadas, una medida de rendimiento) usando el pequeño conjunto de covariables disponibles en la
Pitching
tabla. ¿Cómo funciona la relación (lineal) entreW
(victorias) yERA
dependiendo de qué otras covariables se incluyen en la especificación?Aquí hay un breve guión que aprovecha el poder del
.SD
cual explora esta pregunta:El coeficiente siempre tiene el signo esperado (los mejores lanzadores tienden a tener más victorias y menos carreras permitidas), pero la magnitud puede variar sustancialmente dependiendo de qué más controlemos.
Uniones condicionales
data.table
La sintaxis es hermosa por su simplicidad y robustez. La sintaxisx[i]
maneja de manera flexible dos enfoques comunes de subconjunto: cuandoi
es unlogical
vector,x[i]
devolverá esas filasx
correspondientes a dondei
estáTRUE
; cuandoi
es otrodata.table
,join
se realiza a (en forma simple, usando lakey
s dex
yi
, de lo contrario, cuandoon =
se especifica, usando coincidencias de esas columnas).Esto es genial en general, pero se queda corto cuando deseamos realizar una unión condicional , en donde la naturaleza exacta de la relación entre tablas depende de algunas características de las filas en una o más columnas.
Este ejemplo es un poco artificial, pero ilustra la idea; ver aquí ( 1 , 2 ) para más.
El objetivo es agregar una columna
team_performance
a laPitching
tabla que registre el desempeño del equipo (rango) del mejor lanzador en cada equipo (medido por la efectividad más baja, entre los lanzadores con al menos 6 juegos registrados).Tenga en cuenta que la
x[y]
sintaxis devuelvenrow(y)
valores, razón por la cual.SD
está a la derecha enTeams[.SD]
(ya que el RHS de:=
en este caso requierenrow(Pitching[rank_in_team == 1])
valores..SD
Operaciones agrupadasA menudo, nos gustaría realizar alguna operación en nuestros datos a nivel de grupo . Cuando especificamos
by =
(okeyby =
), el modelo mental de lo que sucede cuando losdata.table
procesosj
es pensardata.table
que se divide en muchos subcomponentesdata.table
, cada uno de los cuales corresponde a un solo valor de suby
(s) variable (s):En este caso,
.SD
es de naturaleza múltiple: se refiere a cada uno de estos subdata.table
, uno a la vez (un poco más exactamente, el alcance de.SD
un sub-data.table
). Esto nos permite expresar de manera concisa una operación que nos gustaría realizar en cada sub-data.table
antes de que el resultado reensamblado nos sea devuelto.Esto es útil en una variedad de configuraciones, las más comunes de las cuales se presentan aquí:
Subconjunto de grupo
Obtengamos la temporada de datos más reciente para cada equipo en los datos de Lahman. Esto se puede hacer simplemente con:
Recuerde que en
.SD
sí mismo es undata.table
, y que se.N
refiere al número total de filas en un grupo (es igual anrow(.SD)
dentro de cada grupo), por lo que.SD[.N]
devuelve la totalidad de.SD
la fila final asociada a cada unoteamID
.Otra versión común de esto es usar
.SD[1L]
en su lugar para obtener la primera observación para cada grupo.Grupo Optima
Supongamos que queremos devolver el mejor año para cada equipo, medido por su número total de carreras anotadas (
R
por supuesto, podríamos ajustar esto fácilmente para referirnos a otras métricas). En lugar de tomar un elemento fijo de cada sub-data.table
, ahora definimos el índice deseado dinámicamente de la siguiente manera:Tenga en cuenta que, por supuesto, este enfoque se puede combinar
.SDcols
para devolver solo partes dedata.table
cada uno.SD
(con la advertencia que.SDcols
debe corregirse en los distintos subconjuntos)NB :
.SD[1L]
actualmente está optimizado porGForce
( vea también ),data.table
componentes internos que aceleran masivamente las operaciones agrupadas más comunes comosum
omean
- vea?GForce
para más detalles y esté atento / soporte de voz para solicitudes de mejoras de características para actualizaciones en este frente: 1 , 2 , 3 , 4 , 5 , 6Regresión Agrupada
Volviendo a la consulta anterior sobre la relación entre
ERA
yW
, supongamos que esperamos que esta relación difiera según el equipo (es decir, hay una pendiente diferente para cada equipo). Podemos volver a ejecutar fácilmente esta regresión para explorar la heterogeneidad en esta relación de la siguiente manera (observando que los errores estándar de este enfoque son generalmente incorrectos, la especificaciónERA ~ W*teamID
será mejor, este enfoque es más fácil de leer y los coeficientes están bien) :Si bien existe una buena cantidad de heterogeneidad, existe una concentración clara alrededor del valor general observado
¡Esperemos que esto haya aclarado el poder de
.SD
facilitar un código hermoso y eficientedata.table
!fuente
Hice un video sobre esto después de hablar con Matt Dowle sobre .SD, puedes verlo en YouTube: https://www.youtube.com/watch?v=DwEzQuYfMsI
fuente