.SD
semble utile mais je ne sais pas vraiment ce que je fais avec. Qu'est ce que cela signifie? Pourquoi y a-t-il une période précédente (point). Que se passe-t-il lorsque je l'utilise?
J'ai lu:
.SD
est un data.table
contenant le sous-ensemble de x
données de pour chaque groupe, à l'exclusion des colonnes de groupe. Il peut être utilisé lors du regroupement par i
, lors du regroupement par by
, par clé by
et _ad hoc_by
Cela signifie-t-il que la fille data.table
est gardée en mémoire pour la prochaine opération?
r
data.table
Farrel
la source
la source
?data.table
a été amélioré dans la v1.7.10, grâce à cette question. Il explique maintenant le nom.SD
selon la réponse acceptée.Réponses:
.SD
signifie quelque chose comme "S
ubset ofD
ata.table". Il n'y a pas de signification pour l'initiale"."
, sauf que cela rend encore plus improbable qu'il y ait un conflit avec un nom de colonne défini par l'utilisateur.S'il s'agit de votre data.table:
Cela peut vous aider à voir ce que
.SD
c'est:Fondamentalement, l'
by=y
instruction divise la table de données d'origine en ces deux sous-data.tables
et opère sur eux à leur tour.
Pendant qu'il fonctionne sur l'un ou l'autre, il vous permet de faire référence au sous-marin actuel
data.table
en utilisant le pseudo / poignée / symbole.SD
. C'est très pratique, car vous pouvez accéder aux colonnes et les utiliser comme si vous étiez assis à la ligne de commande en travaillant avec une seule table data.table appelée.SD
... sauf qu'ici,data.table
effectuera ces opérations sur chaque sous-data.table
défini par combinaisons de touches, les "coller" ensemble et renvoyer les résultats en un seuldata.table
!la source
.SD
estDT[,print(.SD),by=y]
.DT[,print(.SD[,y]),by=y]
, indique que j'ai accès à la valeur dey
, même si cela ne fait pas partie de.SD
. D'où est la valeur de lay
portée? Est-il disponible b / c c'est la valeur actuelle deby
?.SD[,y]
est undata.table
sous-ensemble régulier, donc depuisy
n'est pas une colonne de.SD
celui - ci regarde dans l'environnement qui l'a appelé, qui dans ce cas est l'j
environnement (de laDT
requête) où lesby
variables sont disponibles. S'il ne s'y trouve pas, il regarde dans le parent, et son parent et ainsi de suite de la manière R habituelle. (Eh bien, via la portée héritée de la jointure, également, qui n'est pas utilisée dans ces exemples car il n'y en a pasi
).by=list(x,y,z)
signifieraitx
,y
etz
sont à la dispositionj
. Pour un accès générique, ils sont également intégrés.BY
. La FAQ 2.10 a un peu d'histoire à ce sujet, mais une certaine clarté pourrait être ajoutée?data.table
. Super, l'aide docu serait la bienvenue. Encore mieux si vous souhaitez rejoindre un projet et changer directement.Éditer:
Compte tenu de la satisfaction de cette réponse, je l'ai convertie en une vignette de package maintenant disponible ici
Compte tenu de la fréquence à laquelle cela se produit, je pense que cela mérite un peu plus d'exposé, au-delà de la réponse utile donnée par Josh O'Brien ci-dessus.
En plus du S ubset de l' acronyme D ata habituellement cité / créé par Josh, je pense qu'il est également utile de considérer le "S" pour signifier "Selfsame" ou "Self-reference" -
.SD
est dans sa forme la plus élémentaire un référence réflexive àdata.table
lui-même - comme nous le verrons dans les exemples ci-dessous, cela est particulièrement utile pour enchaîner des "requêtes" (extractions / sous-ensembles / etc en utilisant[
). En particulier, cela signifie également que.SD
c'est luidata.table
- même un (avec la mise en garde qu'il ne permet pas l'affectation avec:=
).L'utilisation plus simple de
.SD
est pour le sous-ensemble de colonnes (c'est-à-dire quand.SDcols
est spécifié); Je pense que cette version est beaucoup plus simple à comprendre, nous allons donc en parler en premier ci-dessous. L'interprétation de.SD
dans sa deuxième utilisation, les scénarios de regroupement (c'est-à-dire, quandby =
oukeyby =
est spécifié), est légèrement différente, conceptuellement (même si au fond c'est la même chose, car, après tout, une opération non groupée est un cas limite de groupement avec juste un groupe).Voici quelques exemples illustratifs et quelques autres exemples d'usages que j'implémente souvent moi-même:
Chargement des données Lahman
Pour donner à cela une sensation plus réelle, plutôt que de créer des données, chargeons des ensembles de données sur le baseball à partir de
Lahman
:Nu
.SD
Pour illustrer ce que je veux dire sur la nature réflexive de
.SD
, considérons son utilisation la plus banale:Autrement dit, nous venons de revenir
Pitching
, c'est-à-dire que c'était une façon d'écrire trop verbeusePitching
ouPitching[]
:En termes de sous-ensemble,
.SD
est toujours un sous-ensemble des données, c'est juste un élément trivial (l'ensemble lui-même).Sous-ensemble de colonnes:
.SDcols
La première façon d'avoir un impact sur ce qui
.SD
est est de limiter les colonnes contenues dans l'.SD
utilisation de l'.SDcols
argument à[
:C'est juste à titre d'illustration et c'était assez ennuyeux. Mais même cette utilisation simple se prête à une grande variété d'opérations de manipulation de données hautement bénéfiques / omniprésentes:
Conversion de type de colonne
La conversion de type de colonne est une réalité pour le munging de données - à partir de cette écriture,
fwrite
ne peut pas lire automatiquementDate
ouPOSIXct
colonnes , et les conversions entrecharacter
/factor
/numeric
sont courantes. Nous pouvons utiliser.SD
et.SDcols
convertir par lots des groupes de telles colonnes.Nous remarquons que les colonnes suivantes sont stockées comme
character
dans l'Teams
ensemble de données:Si vous ne savez pas comment utiliser
sapply
ici, notez que c'est la même chose que pour la base Rdata.frames
:La clé pour comprendre cette syntaxe est de rappeler que a
data.table
(ainsi que adata.frame
) peut être considéré comme unlist
où chaque élément est une colonne - ainsi,sapply
/lapply
s'appliqueFUN
à chaque colonne et renvoie le résultat commesapply
/ lelapply
ferait habituellement (ici,FUN == is.character
renvoie unlogical
de longueur 1,sapply
renvoie donc un vecteur).La syntaxe pour convertir ces colonnes
factor
est très similaire - ajoutez simplement l':=
opérateur d'affectationNotez que nous devons mettre
fkt
entre parenthèses()
pour forcer R à interpréter cela comme des noms de colonnes, au lieu d'essayer d'attribuer le nomfkt
au RHS.La flexibilité de
.SDcols
(et:=
) pour accepter uncharacter
vecteur ou uninteger
vecteur de positions de colonne peut également être utile pour la conversion basée sur des modèles de noms de colonnes *. Nous pourrions convertir toutes lesfactor
colonnes encharacter
:Et puis convertissez toutes les colonnes qui contiennent de
team
nouveau enfactor
:** L' utilisation explicite des numéros de colonne (comme
DT[ , (1) := rnorm(.N)]
) est une mauvaise pratique et peut entraîner une corruption silencieuse du code au fil du temps si les positions des colonnes changent. Même l'utilisation implicite de nombres peut être dangereuse si nous ne gardons pas un contrôle intelligent / strict sur l'ordre du moment où nous créons l'index numéroté et quand nous l'utilisons.Contrôle du RHS d'un modèle
La spécification variable des modèles est une caractéristique essentielle d'une analyse statistique robuste. Essayons de prédire l'ERA (Earned Runs Average, une mesure de la performance) d'un lanceur en utilisant le petit ensemble de covariables disponibles dans le
Pitching
tableau. Comment la relation (linéaire) entreW
(gagne) etERA
varie-t-elle en fonction des autres covariables incluses dans la spécification?Voici un court script exploitant la puissance
.SD
dont explore cette question:Le coefficient a toujours le signe attendu (les meilleurs lanceurs ont tendance à avoir plus de victoires et moins de courses autorisées), mais la magnitude peut varier considérablement en fonction de ce que nous contrôlons d'autre.
Jointures conditionnelles
data.table
la syntaxe est belle pour sa simplicité et sa robustesse. La syntaxex[i]
gère avec souplesse deux approches courantes du sous-ensemble - quandi
est unlogical
vecteur,x[i]
retournera ces lignes dex
correspondant à oùi
estTRUE
; quand eni
est un autredata.table
, ajoin
est exécuté (sous forme simple, en utilisant lekey
s dex
eti
, sinon, quandon =
est spécifié, en utilisant les correspondances de ces colonnes).C'est génial en général, mais cela échoue lorsque nous souhaitons effectuer une jointure conditionnelle , dans laquelle la nature exacte de la relation entre les tables dépend de certaines caractéristiques des lignes dans une ou plusieurs colonnes.
Cet exemple est un peu artificiel, mais illustre l'idée; voir ici ( 1 , 2 ) pour plus.
Le but est d'ajouter une colonne
team_performance
auPitching
tableau qui enregistre la performance de l'équipe (rang) du meilleur lanceur de chaque équipe (telle que mesurée par l'ERA la plus basse, parmi les lanceurs avec au moins 6 matchs enregistrés).Notez que la
x[y]
syntaxe renvoie desnrow(y)
valeurs, c'est pourquoi se.SD
trouve à droite dansTeams[.SD]
(puisque le RHS de:=
dans ce cas nécessite desnrow(Pitching[rank_in_team == 1])
valeurs..SD
Opérations groupéesSouvent, nous souhaitons effectuer une opération sur nos données au niveau du groupe . Lorsque nous spécifions
by =
(oukeyby =
), le modèle mental de ce qui se passe lorsque lesdata.table
processusj
doivent penser que vousdata.table
êtes divisé en plusieurs sous-composantsdata.table
, chacun correspondant à une seule valeur de votre ou vosby
variables:Dans ce cas,
.SD
est de nature multiple - il se réfère à chacun de ces sous-data.table
s, un à la fois (un peu plus précisément, la portée de.SD
est un seul sous-data.table
). Cela nous permet d'exprimer de manière concise une opération que nous aimerions effectuer sur chaque sous-ensembledata.table
avant que le résultat réassemblé ne nous soit renvoyé.Ceci est utile dans une variété de paramètres, dont les plus courants sont présentés ici:
Sous-ensemble de groupe
Obtenons la saison la plus récente de données pour chaque équipe dans les données de Lahman. Cela peut être fait tout simplement avec:
Rappelez-vous que
.SD
c'est lui-même undata.table
, et qui.N
fait référence au nombre total de lignes dans un groupe (il est égal ànrow(.SD)
dans chaque groupe), donc.SD[.N]
renvoie l' intégralité de.SD
pour la dernière ligne associée à chacunteamID
.Une autre version courante de ceci est d'utiliser à la
.SD[1L]
place pour obtenir la première observation pour chaque groupe.Groupe Optima
Supposons que nous voulions renvoyer la meilleure année pour chaque équipe, mesurée par le nombre total de points marqués (
R
; nous pourrions facilement l'ajuster pour faire référence à d'autres mesures, bien sûr). Au lieu de prendre un élément fixe de chaque sous-data.table
, nous définissons maintenant l'index souhaité dynamiquement comme suit:Notez que cette approche peut bien sûr être combinée avec
.SDcols
pour ne renvoyer que des parties dedata.table
pour chacun.SD
(avec la mise en garde qui.SDcols
doit être corrigée dans les différents sous-ensembles)NB :
.SD[1L]
est actuellement optimisé parGForce
( voir aussi ), desdata.table
internes qui accélèrent massivement les opérations groupées les plus courantes commesum
oumean
- voir?GForce
pour plus de détails et garder un œil sur / support vocal pour les demandes d'amélioration des fonctionnalités pour les mises à jour sur ce front: 1 , 2 , 3 , 4 , 5 , 6Régression groupée
Pour revenir à l'enquête ci-dessus concernant la relation entre
ERA
etW
, supposons que nous nous attendions à ce que cette relation diffère d'une équipe à l'autre (c'est-à-dire qu'il existe une pente différente pour chaque équipe). Nous pouvons facilement réexécuter cette régression pour explorer l'hétérogénéité de cette relation comme suit (en notant que les erreurs standard de cette approche sont généralement incorrectes - la spécificationERA ~ W*teamID
sera meilleure - cette approche est plus facile à lire et les coefficients sont corrects) :Bien qu'il y ait une assez grande hétérogénéité, il y a une concentration distincte autour de la valeur globale observée
Espérons que cela a élucidé le pouvoir de
.SD
faciliter un code beau et efficacedata.table
!la source
J'ai fait une vidéo à ce sujet après avoir parlé avec Matt Dowle de .SD, vous pouvez la voir sur YouTube: https://www.youtube.com/watch?v=DwEzQuYfMsI
la source