Data.table: fonctions mobiles, agrĂ©gats mobiles, fenĂȘtre glissante, moyenne mobile

CrĂ©Ă© le 21 avr. 2018  Â·  39Commentaires  Â·  Source: Rdatatable/data.table

Pour rassembler les exigences en un seul endroit et actualiser les discussions d'environ 4 ans crĂ©ant ce problĂšme pour couvrir la fonctionnalitĂ© _fonctions mobiles_ (Ă©galement appelĂ©es _agrĂ©gats mobiles_, _fenĂȘtre coulissante_ ou _moyenne mobile_/_agrĂ©gats mobiles_).

fonctions de roulement

  • [x] moyenne de rouleau
  • [x] rollsum
  • [ ] rollmin
  • [ ] rollmax
  • [ ] rouleau mĂ©dian
  • [ ] rollprod
  • [ ] rollsd
  • [ ] rollvar
  • [ ] classement
  • [x] rollapply (AMUSEMENT fourni par l'utilisateur)
  • [ ] rollregression (trĂšs demandĂ©)
  • [ ] rollcor?
  • [ ] rollcov?

caractéristiques

  • [x] plusieurs colonnes Ă  la fois
  • [x] plusieurs fenĂȘtres Ă  la fois
  • [x] plusieurs colonnes et plusieurs fenĂȘtres Ă  la fois
  • [x] entrĂ©e de vecteurs atomiques et fenĂȘtre unique renvoie des vecteurs atomiques
  • [x] liste de vecteurs de diffĂ©rentes longueurs
  • [x] aligner : gauche/centre/droite
  • [x] gĂ©rer les NA
  • [x] constante de remplissage
  • [x] support vectoriel long
  • [ ] prise en charge partielle de la fenĂȘtre (si nĂ©cessaire peut ĂȘtre trouvĂ© dans ea766f2499034cedf6abf872440268b78979147c)
  • [x] prise en charge de la fenĂȘtre adaptative
  • [x] utilise openmp pour parallĂ©liser le calcul de plusieurs colonnes/fenĂȘtres
  • [x] correction d'erreur d'arrondi
  • [x] timing en mode verbeux Ă  partir de la rĂ©gion parallĂšle (bloquĂ© par ~#3422~, #3423)
feature request

Commentaire le plus utile

@mattdowle répondant aux questions des relations publiques

Pourquoi faisons-nous cela dans data.table ? Pourquoi l'intégrons-nous au lieu de contribuer aux packages existants et de les utiliser à partir de data.table ?

  1. Il y a eu 3 problĂšmes diffĂ©rents crĂ©Ă©s pour demander cette fonctionnalitĂ© dans data.table. Également plusieurs questions SO Ă©tiquetĂ©es data.table. Les utilisateurs s'attendent Ă  ce que cela soit dans la portĂ©e de data.table.
  2. data.table s'adapte parfaitement aux données de séries chronologiques et les agrégats glissants sont des statistiques assez utiles là-bas.

je suppose que cela se rĂ©sume Ă  la syntaxe (fonctionnalitĂ©s possibles ou pratiques uniquement si elles sont intĂ©grĂ©es Ă  data.table ; par exemple, Ă  l'intĂ©rieur [...] et optimisĂ©es) et Ă  la construction des Ă©lĂ©ments internes de data.table dans la fonction de roulement au niveau C ; Par exemple, froll* doit ĂȘtre conscient et utiliser les indices et la clĂ© data.table. Si c'est le cas, plus de dĂ©tails Ă  ce sujet sont nĂ©cessaires ; par exemple un court exemple simple.

Pour moi personnellement c'est une question de vitesse et de manque de chaßne de dépendances, aujourd'hui pas facile à réaliser.
Les clĂ©s/indices peuvent ĂȘtre utiles pour frollmin/frollmax, mais il est peu probable que l'utilisateur crĂ©e un index sur la variable de mesure. Il est peu probable que l'utilisateur fasse un index sur la variable de mesure, nous n'avons pas encore fait cette optimisation pour min/max. Je ne vois pas beaucoup de sens pour l'optimisation GForce car la mĂ©moire allouĂ©e n'est pas libĂ©rĂ©e aprĂšs l'appel roll* mais renvoyĂ©e en tant que rĂ©ponse (par opposition Ă  la moyenne non glissante, Ă  la somme, etc.).

S'il n'y a pas d'argument convaincant pour l'intégration, alors nous devrions plutÎt contribuer aux autres packages.

J'en ai Ă©numĂ©rĂ© quelques-uns ci-dessus, si vous n'ĂȘtes pas convaincu, je vous recommande de remplir une question aux utilisateurs de data.table, de demander sur twitter, etc. pour vĂ©rifier la rĂ©ponse. Cette fonctionnalitĂ© Ă©tait demandĂ©e depuis longtemps et par de nombreux utilisateurs. Si la rĂ©ponse ne vous convainc pas, vous pouvez fermer ce problĂšme.

Tous les 39 commentaires

Implémentation de rollmean proposée, simplifiée.

x = data.table(v1=1:5, v2=1:5)
k = c(2, 3)
i - single column
j - single window
m - int referring to single row
w - current row's sum of rolling window
r - answer for each i, j



md5-be70673ef4a3bb883d4f334bd8fadec9



for i in x
  for j in k
  r = NA_real_
  w = 0
    for m in 1:length(i)
      w = w + i[m]
      w = w - i[m-j]
      r[m] = w / j

oui, et de nombreuses autres fonctions roulĂ©es suivent la mĂȘme idĂ©e de base (y compris
écart type glissant/tout moment basé sur les attentes, et toute fonction
comme rollproduct qui utilise inversible * au lieu de + pour agréger au sein
la fenĂȘtre

J'ai toujours envisagĂ© la fonctionnalitĂ© de fenĂȘtre mobile en regroupant l'ensemble de donnĂ©es en plusieurs groupes qui se chevauchent (fenĂȘtres). L'API ressemblerait alors Ă  ceci :

DT[i, j,
   by = roll(width=5, align="center")]

Ensuite, si j contient, disons, mean(A) , nous pouvons le remplacer en interne par rollmean(A) -- exactement comme nous le faisons avec gmean() ce moment. Ou j peut contenir une fonctionnalitĂ© arbitrairement compliquĂ©e (par exemple, exĂ©cuter une rĂ©gression pour chaque fenĂȘtre), auquel cas nous lui fournirions .SD data.table -- exactement comme nous le faisons avec les groupes Ă  l'heure actuelle.

De cette façon, il n'est pas nécessaire d'introduire plus de 10 nouvelles fonctions, une seule. Et l'esprit data.table-y est également ressenti.

Oui d'accord

Le samedi 21 avril 2018, 15h38 Pasha Stetsenko [email protected]
a Ă©crit:

J'ai toujours envisagĂ© la fonctionnalitĂ© de fenĂȘtre mobile comme regroupant les
ensemble de donnĂ©es en plusieurs groupes qui se chevauchent (fenĂȘtres). Ensuite, l'API regarderait
quelque chose comme ça:

DT[i, j,
by = roll(width=5, align="center")]

Ensuite, si j contient, disons, moyenne (A), nous pouvons le remplacer en interne par
rollmean(A) -- exactement comme nous le faisons avec gmean() en ce moment. Ou je peux
contenir une fonctionnalité arbitrairement compliquée (par exemple, exécuter une régression pour
chaque fenĂȘtre), auquel cas nous lui fournirions .SD data.table -- exactement
comme nous le faisons avec les groupes en ce moment.

De cette façon, il n'est pas nécessaire d'introduire plus de 10 nouvelles fonctions, une seule. Et cela
se sent data.table-y dans l'esprit aussi.

-
Vous recevez ceci parce que vous avez commenté.
RĂ©pondez directement Ă  cet e-mail, consultez-le sur GitHub
https://github.com/Rdatatable/data.table/issues/2778#issuecomment-383275134 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AHQQdbADiE4aAI1qPxPnFXUM5gR-0w2Tks5tquH8gaJpZM4TeTQf
.

@st-pasha idée intéressante, ressemble à l'esprit data.table-y, mais elle imposera de nombreuses limitations et n'est pas vraiment appropriée pour cette catégorie de fonctions.


  • comment effectuer rollmean par groupe
DT[, rollmean(V1, 3), by=V2]
  • comment calculer diffĂ©rentes tailles de fenĂȘtre pour diffĂ©rentes colonnes
DT[, .(rollmean(V1, 3), rollmean(V2, 100))]
  • comment calculer rollmean en dehors de [.data.table car nous autorisons maintenant le dĂ©calage
rollmean(rnorm(10), 3)
  • comment prendre en charge des requĂȘtes telles que
DT[, .(rollmean(list(V1, V2), c(5, 20)), rollmean(list(V2, V3), c(10, 30)))]
  • comment appeler mean et rollmean dans le mĂȘme j appel
DT[, .(rollmean(V1, 3), mean(V1)), by=V2]

Habituellement, lorsque vous utilisez by nous agrĂ©geons les donnĂ©es sur un plus petit nombre de lignes, tandis que les fonctions de roulement renvoient toujours un vecteur de mĂȘme longueur que l'entrĂ©e. Ces types de fonctions dans SQL ont une API dans le style suivant :

SELECT AVG(value) OVER (ROWS BETWEEN 99 PRECEDING AND CURRENT ROW)
FROM tablename;

Vous pouvez toujours le combiner avec GROUP BY comme suit :

SELECT AVG(value) OVER (ROWS BETWEEN 99 PRECEDING AND CURRENT ROW)
FROM tablename
GROUP BY group_columns;

Donc, en SQL, ces fonctions restent dans SELECT ce qui fait référence à j dans DT.
Dans DT, nous pourrions obtenir la mĂȘme chose avec :

DT[, rollmean(value, 100)]
DT[, rollmean(value, 100), group_columns]

Les fonctions de roulement entrent dans la mĂȘme catĂ©gorie de fonctions que shift qui renvoie Ă©galement le mĂȘme nombre de lignes que celles obtenues en entrĂ©e.
Le décalage dans SQL ressemble à :

SELECT LAG(value, 1) OVER ()
FROM tablename;

mean et rollmean ne sont pas seulement des fonctions diffĂ©rentes, ce sont des catĂ©gories de fonctions diffĂ©rentes. L'un voulait agrĂ©ger selon le groupe, un autre pas agrĂ©ger du tout. Ceci est facilement visible dans SQL oĂč nous n'utilisons pas GROUP BY pour le type de fonctions de roulement mais nous devons utiliser GROUP BY pour des agrĂ©gats comme mean (obtenant finalement le total de la subvention lors du regroupement la clause n'est pas prĂ©sente).
Je ne vois pas de raisonnement solide pour essayer d'appliquer les mĂȘmes rĂšgles d'optimisation que nous pour mean , surtout quand cela ne correspond pas vraiment au cas d'utilisation, et tout cela juste pour le bien des donnĂ©es.table-y esprit. La proposition actuelle est Ă©galement l'esprit data.table-y, il peut facilement ĂȘtre combinĂ© avec := , comme shift . Il ajoute simplement un ensemble de nouvelles fonctions, actuellement non disponibles dans data.table.

@jangorecki Merci, ce sont toutes des considĂ©rations valables. Bien sĂ»r, diffĂ©rentes personnes ont des expĂ©riences diffĂ©rentes et des points de vue diffĂ©rents sur ce qui devrait ĂȘtre considĂ©rĂ© comme « naturel ».

Il est possible d'effectuer rollmean par groupe : il s'agit simplement d'un regroupement Ă  2 niveaux : DT[, mean(V1), by=.(V2, roll(3))] . Cependant je ne vois pas comment faire diffĂ©rentes tailles de fenĂȘtre sur diffĂ©rentes colonnes avec ma syntaxe...

Je dois admettre que je n'ai jamais vu la syntaxe SQL pour les jointures tournantes auparavant. Il est intĂ©ressant de noter qu'ils utilisent un agrĂ©gateur standard tel que AVG tout en y appliquant la spĂ©cification de fenĂȘtrage. En regardant la documentation Transact-SQL, il y a quelques idĂ©es intĂ©ressantes, par exemple la distinction entre la sĂ©lection de ligne logique/physique. Ils autorisent diffĂ©rents opĂ©rateurs "OVER" sur diffĂ©rentes colonnes, mais dans tous les exemples qu'ils donnent, il s'agit de la mĂȘme clause OVER rĂ©pĂ©tĂ©e plusieurs fois. Cela suggĂšre donc que ce cas d'utilisation est beaucoup plus courant, et donc l'utilisation d'un seul groupe roll() entraĂźnerait moins de rĂ©pĂ©titions.

De plus, cette question SO fournit un aperçu intéressant de la raison pour laquelle la syntaxe OVER a été introduite dans SQL :

Vous pouvez utiliser GROUP BY SalesOrderID. La diffĂ©rence est qu'avec GROUP BY, vous ne pouvez avoir que les valeurs agrĂ©gĂ©es pour les colonnes qui ne sont pas incluses dans GROUP BY. En revanche, en utilisant des fonctions d'agrĂ©gation fenĂȘtrĂ©es au lieu de GROUP BY, vous pouvez rĂ©cupĂ©rer Ă  la fois des valeurs agrĂ©gĂ©es et non agrĂ©gĂ©es. C'est-Ă -dire que, bien que vous ne le fassiez pas dans votre exemple de requĂȘte, vous pouvez rĂ©cupĂ©rer Ă  la fois les valeurs OrderQty individuelles et leurs sommes, dĂ©comptes, moyennes, etc. sur des groupes de mĂȘmes SalesOrderID.

Il semble donc que la syntaxe soit conçue pour contourner la limitation du SQL standard oĂč les rĂ©sultats de regroupement ne peuvent pas ĂȘtre combinĂ©s avec des valeurs non agrĂ©gĂ©es (c'est-Ă -dire en sĂ©lectionnant Ă  la fois A et mean(A) dans la mĂȘme expression). Cependant data.table n'a pas une telle limitation, il a donc plus de libertĂ© dans son choix de syntaxe.


Maintenant, si nous voulons vraiment prendre une longueur d'avance, nous devons penser dans une perspective plus large : Ă  quoi servent les fonctions "roulantes", Ă  quoi servent-elles, comment elles peuvent ĂȘtre Ă©tendues, etc. Voici mon avis, Ă  venir du point de vue d'un statisticien :

La fonction "Rolling Mean" est utilisĂ©e pour lisser certaines entrĂ©es bruyantes. Disons, si vous avez des observations dans le temps et que vous voulez avoir une notion de "quantitĂ© moyenne", qui varierait nĂ©anmoins dans le temps bien que trĂšs lentement. Dans ce cas, la « moyenne mobile sur les 100 derniĂšres observations » ou la « moyenne mobile sur toutes les observations prĂ©cĂ©dentes » peuvent ĂȘtre prises en compte. De mĂȘme, si vous observez une certaine quantitĂ© sur une plage d'entrĂ©es, vous pouvez la lisser en appliquant une "moyenne mobile sur ±50 observations".

  • Ainsi, la premiĂšre extension consiste Ă  regarder des "fenĂȘtres lisses": imaginez une moyenne sur des observations passĂ©es oĂč plus une observation dans le passĂ© est Ă©loignĂ©e, moins sa contribution est. Ou une moyenne d'observations proches sur un noyau gaussien.
  • DeuxiĂšmement, les fenĂȘtres adaptatives. Par exemple, si vous avez une entrĂ©e bruitĂ©e dĂ©finie sur un intervalle [0, 1], le lisser Ă  l'aide d'une fenĂȘtre ±N produit un rĂ©sultat biaisĂ© prĂšs des bords. Un estimateur sans biais adapterait la forme de la fenĂȘtre en fonction de la distance par rapport au bord.
  • Lissage de rĂ©Ă©chantillonnage : la restriction de produire exactement autant d'observations que dans les donnĂ©es sources est trop restrictive. Si vous considĂ©rez vos donnĂ©es comme des observations bruyantes d'une fonction sous-jacente, il est parfaitement raisonnable de demander de calculer les valeurs lissĂ©es de cette fonction sur un maillage plus grossier/plus fin que l'entrĂ©e d'origine. Ou peut-ĂȘtre que les donnĂ©es d'origine sont espacĂ©es de maniĂšre irrĂ©guliĂšre et que vous souhaitez les rĂ©Ă©chantillonner sur une grille rĂ©guliĂšre.
  • Jackknife : pour chaque observation, vous souhaitez calculer la moyenne/rĂ©gression sur toutes les observations Ă  l'exception du courant.
  • Division en K : affichez les donnĂ©es sous forme de groupes multiples, chaque groupe n'excluant qu'une petite partie des observations.

Tous ces Ă©lĂ©ments peuvent ĂȘtre implĂ©mentĂ©s en tant qu'opĂ©rateurs de regroupement Ă©tendus, les fenĂȘtres mobiles n'Ă©tant qu'un des Ă©lĂ©ments de cette liste. Cela Ă©tant dit, je ne comprends pas pourquoi nous ne pouvons pas jouer sur les deux tableaux.

Je dois admettre que je n'ai jamais vu la syntaxe SQL pour les jointures tournantes auparavant.

Je suppose que vous voulez dire des fonctions de roulement, le problĂšme n'a rien Ă  voir avec les jointures de roulement.

Ils autorisent diffĂ©rents opĂ©rateurs "OVER" sur diffĂ©rentes colonnes, mais dans tous les exemples qu'ils donnent, il s'agit de la mĂȘme clause OVER rĂ©pĂ©tĂ©e plusieurs fois. Cela suggĂšre donc que ce cas d'utilisation est beaucoup plus courant et que l'utilisation d'un seul groupe roll() entraĂźnerait donc moins de rĂ©pĂ©titions.

C'est juste une question de cas d'utilisation, si vous appelez le mĂȘme OVER() plusieurs fois, vous trouverez peut-ĂȘtre plus performant d'utiliser GROUP BY , de crĂ©er une table de recherche et de la rĂ©utiliser dans d'autres requĂȘtes. Quels que soient les exemples, il est nĂ©cessaire de rĂ©pĂ©ter OVER() pour conserver la caractĂ©ristique de localitĂ© pour chaque mesure fournie. Mes cas d'utilisation des entrepĂŽts de donnĂ©es n'Ă©taient pas aussi simples que ceux des documents Microsoft.

En revanche, en utilisant des fonctions d'agrĂ©gation fenĂȘtrĂ©es au lieu de GROUP BY, vous pouvez rĂ©cupĂ©rer Ă  la fois des valeurs agrĂ©gĂ©es et non agrĂ©gĂ©es.

Dans data.table, nous faisons := et by en une seule requĂȘte pour y parvenir.

Il apparaĂźt donc que la syntaxe est conçue pour contourner la limitation du SQL standard oĂč les rĂ©sultats de regroupement ne peuvent pas ĂȘtre combinĂ©s avec des valeurs non agrĂ©gĂ©es (c'est-Ă -dire en sĂ©lectionnant Ă  la fois A et moyenne(A) dans la mĂȘme expression). Cependant data.table n'a pas une telle limitation, il a donc plus de libertĂ© dans son choix de syntaxe.

Ce n'est pas une grande limitation de SQL mais juste la conception de GROUP BY, qu'il agrĂ©gera, de la mĂȘme maniĂšre que nos agrĂ©gats by . Une nouvelle API Ă©tait nĂ©cessaire pour couvrir les nouvelles fonctionnalitĂ©s de la fenĂȘtre. Le regroupement pour la fonction de fenĂȘtre SQL peut ĂȘtre fourni pour chaque appel de fonction Ă  l'aide de FUN() OVER (PARTITION BY ...) oĂč _partition by_ est comme un regroupement local pour une seule mesure. Donc, pour obtenir la flexibilitĂ© de SQL, nous aurions besoin d'utiliser j = mean(V1, roll=5) ou j = over(mean(V1), roll=5) gardant cette API dans j . NĂ©anmoins, cette approche ne permettra pas de prendre en charge tous les cas d'utilisation mentionnĂ©s ci-dessus.

vous pouvez le lisser en appliquant une "moyenne glissante sur ±50 observations".

C'est Ă  cela que sert l'argument align .

Ainsi, la premiĂšre extension consiste Ă  regarder des "fenĂȘtres lisses": imaginez une moyenne sur des observations passĂ©es oĂč plus une observation dans le passĂ© est Ă©loignĂ©e, moins sa contribution est. Ou une moyenne d'observations proches sur un noyau gaussien.

Il existe de nombreuses variantes (nombre pratiquement illimitĂ©) de moyennes mobiles, la fonction de fenĂȘtre de lissage la plus courante (autre que rollmean/SMA) est la moyenne mobile exponentielle (EMA). Ce qui devrait ĂȘtre inclus, et ce qui ne l'est pas, n'est pas trivial Ă  dĂ©cider, et il est en fait prĂ©fĂ©rable de prendre cette dĂ©cision en fonction des demandes de fonctionnalitĂ©s qui viendront des utilisateurs, jusqu'Ă  prĂ©sent, aucune demande de ce type n'a Ă©tĂ© demandĂ©e.

Tous ces Ă©lĂ©ments peuvent ĂȘtre implĂ©mentĂ©s en tant qu'opĂ©rateurs de regroupement Ă©tendus, les fenĂȘtres mobiles n'Ă©tant qu'un des Ă©lĂ©ments de cette liste.

Certes, ils le peuvent, mais si vous regardez SO et les problÚmes créés dans notre référentiel, vous verrez que ces quelques fonctions de roulement ici sont responsables de 95+% des demandes des utilisateurs. Je suis heureux de travailler sur EMA et d'autres MA (bien que je ne sois pas sûr que data.table soit le meilleur endroit pour ceux-ci), mais en tant que problÚme distinct. Certains utilisateurs, moi inclus, attendent une simple moyenne mobile dans data.table depuis déjà 4 ans.

Voici mon avis, venant du point de vue d'un statisticien

Mon point de vue vient du Data Warehousing (oĂč j'ai utilisĂ© la fonction fenĂȘtre, au moins une fois par semaine) et de l'analyse des tendances des prix (oĂč j'ai utilisĂ© des dizaines de moyennes mobiles diffĂ©rentes).

rollmean brouillon de roll . J'ai trouvé que la plupart des autres packages qui implémentent la moyenne mobile ne sont pas capables de bien gérer les na.rm=FALSE et les NA présents dans l'entrée. Cette implémentation gÚre NA de maniÚre cohérente jusqu'à mean , ce qui impose une surcharge supplémentaire en raison des appels ISNAN . Nous pourrions autoriser l'API à une version plus rapide mais moins sûre si l'utilisateur est sûr qu'il n'y a pas de NA en entrée.
PR est en #2795

@mattdowle répondant aux questions des relations publiques

Pourquoi faisons-nous cela dans data.table ? Pourquoi l'intégrons-nous au lieu de contribuer aux packages existants et de les utiliser à partir de data.table ?

  1. Il y a eu 3 problĂšmes diffĂ©rents crĂ©Ă©s pour demander cette fonctionnalitĂ© dans data.table. Également plusieurs questions SO Ă©tiquetĂ©es data.table. Les utilisateurs s'attendent Ă  ce que cela soit dans la portĂ©e de data.table.
  2. data.table s'adapte parfaitement aux données de séries chronologiques et les agrégats glissants sont des statistiques assez utiles là-bas.

je suppose que cela se rĂ©sume Ă  la syntaxe (fonctionnalitĂ©s possibles ou pratiques uniquement si elles sont intĂ©grĂ©es Ă  data.table ; par exemple, Ă  l'intĂ©rieur [...] et optimisĂ©es) et Ă  la construction des Ă©lĂ©ments internes de data.table dans la fonction de roulement au niveau C ; Par exemple, froll* doit ĂȘtre conscient et utiliser les indices et la clĂ© data.table. Si c'est le cas, plus de dĂ©tails Ă  ce sujet sont nĂ©cessaires ; par exemple un court exemple simple.

Pour moi personnellement c'est une question de vitesse et de manque de chaßne de dépendances, aujourd'hui pas facile à réaliser.
Les clĂ©s/indices peuvent ĂȘtre utiles pour frollmin/frollmax, mais il est peu probable que l'utilisateur crĂ©e un index sur la variable de mesure. Il est peu probable que l'utilisateur fasse un index sur la variable de mesure, nous n'avons pas encore fait cette optimisation pour min/max. Je ne vois pas beaucoup de sens pour l'optimisation GForce car la mĂ©moire allouĂ©e n'est pas libĂ©rĂ©e aprĂšs l'appel roll* mais renvoyĂ©e en tant que rĂ©ponse (par opposition Ă  la moyenne non glissante, Ă  la somme, etc.).

S'il n'y a pas d'argument convaincant pour l'intégration, alors nous devrions plutÎt contribuer aux autres packages.

J'en ai Ă©numĂ©rĂ© quelques-uns ci-dessus, si vous n'ĂȘtes pas convaincu, je vous recommande de remplir une question aux utilisateurs de data.table, de demander sur twitter, etc. pour vĂ©rifier la rĂ©ponse. Cette fonctionnalitĂ© Ă©tait demandĂ©e depuis longtemps et par de nombreux utilisateurs. Si la rĂ©ponse ne vous convainc pas, vous pouvez fermer ce problĂšme.

J'ai trouvé que sparklyr peut trÚs bien prendre en charge les fonctions de roulement dans un ensemble de données à trÚs grande échelle.

@harryprince pourrait mettre un peu plus de lumiÚre en fournissant un exemple de code de la façon dont vous le faites dans sparklyr ?
Selon "Fonctions de fenĂȘtre" dplyr vignette

Les agrĂ©gats roulants fonctionnent dans une fenĂȘtre de largeur fixe. Vous ne les trouverez pas dans la base R ou dans dplyr, mais il existe de nombreuses implĂ©mentations dans d'autres packages, tels que RcppRoll.

AFAIU, vous utilisez une API Spark personnalisée via sparklyr pour laquelle l'interface dplyr n'est pas implémentée, n'est-ce pas ?

Ce problĂšme concerne les agrĂ©gats roulants, d'autres "types" de fonctions de fenĂȘtre sont dĂ©jĂ  dans data.table depuis longtemps.

Fournir un exemple afin que nous puissions comparer les performances (en mémoire) par rapport à sparklyr / SparkR serait également utile.

Il m'est juste venu Ă  l'esprit que cette question:

comment calculer diffĂ©rentes tailles de fenĂȘtre pour diffĂ©rentes colonnes ?

a en fait une portée plus large, et ne s'applique pas uniquement aux fonctions de roulement.

Par exemple, il semble parfaitement raisonnable de demander comment sĂ©lectionner le prix moyen d'un produit par date, puis par semaine, puis peut-ĂȘtre par semaine+catĂ©gorie, le tout dans la mĂȘme requĂȘte. Si jamais nous devions implĂ©menter une telle fonctionnalitĂ©, la syntaxe naturelle pour cela pourrait ĂȘtre

DT[, .( mean(price, by=date), 
        mean(price, by=week), 
        mean(price, by=c(week, category)) )]

Maintenant, si cette fonctionnalité avait déjà été implémentée, cela aurait été un simple saut à partir de là vers des moyens de roulement :

DT[, .( mean(price, roll=5), 
        mean(price, roll=20), 
        mean(price, roll=100) )]

Je ne dis pas que c'est sans équivoque mieux que rollmean(price, 5) - je propose juste quelques alternatives à considérer...

@st-pacha

comment sĂ©lectionner le prix moyen du produit par date, puis par semaine, puis peut-ĂȘtre par semaine + catĂ©gorie - le tout dans la mĂȘme requĂȘte.

AFAIU, cela est déjà possible en utilisant ?groupingsets , mais pas encore connecté à [.data.table .

@jangorecki , @st-pasha , and Co. -- Merci pour tout votre travail sur ce sujet ! Je suis curieux de savoir pourquoi la prise en charge partielle des fenĂȘtres a Ă©tĂ© supprimĂ©e de la portĂ©e, est-il possible que cette fonctionnalitĂ© revienne sur la feuille de route ? Cela me serait parfois utile et comblerait une lacune de fonctionnalitĂ© qui, Ă  ma connaissance, n'a pas Ă©tĂ© comblĂ©e soit zoo ou RcppRoll .

Cette question de débordement de pile est un bon exemple d'une application continue qui pourrait bénéficier d'un argument partial = TRUE .

@msummersgill Merci pour vos commentaires. Dans le premier article, j'ai explicitement liĂ© commit sha oĂč le code de fonction de fenĂȘtre partielle peut ĂȘtre trouvĂ©. L'implĂ©mentation qui s'y trouve a ensuite Ă©tĂ© supprimĂ©e pour rĂ©duire la complexitĂ© du code. Il imposait Ă©galement un faible coĂ»t de performance mĂȘme lorsqu'il n'utilisait pas cette fonctionnalitĂ©. Cette fonctionnalitĂ© peut (et devrait probablement) ĂȘtre implĂ©mentĂ©e dans l'autre sens, d'abord complĂ©tĂ©e telle quelle, puis remplissez simplement la fenĂȘtre partielle manquante Ă  l'aide d'une boucle supplĂ©mentaire de 1:window_size . Ainsi, la surcharge de cette fonctionnalitĂ© n'est perceptible que lorsque vous l'utilisez. NĂ©anmoins, nous fournissons cette fonctionnalitĂ© via l'argument adaptive , oĂč la fonctionnalitĂ© partial n'est qu'un cas particulier de la moyenne mobile adaptive . Il y a un exemple comment rĂ©aliser partial utilisant adaptive dans ?froll manual . Collez-le ici :

d = as.data.table(list(1:6/2, 3:8/4))
an = function(n, len) c(seq.int(n), rep(n, len-n))
n = an(3, nrow(d))
frollmean(d, n, adaptive=TRUE)

Bien sĂ»r, ce ne sera pas aussi efficace que la fonction de roulement non adaptative utilisant une boucle supplĂ©mentaire pour remplir une fenĂȘtre partielle.
AFAIK zoo a une fonction partial .

Avez-vous l'intention d'ajouter des fonctions de régression glissante à data.table ?

@waynelapierre s'il y aura une demande pour ça, alors oui. tu as mon +1

merci c'est super. Juste une question cependant. Je ne vois que des agrégats roulants simples, comme un moyen roulant ou une médiane roulante. Implémentez-vous également des fonctions de roulement plus raffinées telles que des trames de données DT de roulement ? Dites, créez un DT roulant en utilisant les 10 derniers obs et exécutez une régression lm dessus.

Merci!

@randomgambit Je dirais que c'est hors de portĂ©e, Ă  moins qu'il n'y ait une forte demande pour cela. Il ne serait pas trĂšs difficile de le faire pour ĂȘtre plus rapide que la base R/zoo simplement en gĂ©rant la boucle imbriquĂ©e en C. Mais nous devrions essayer de l'implĂ©menter en utilisant l'algorithme "en ligne", pour Ă©viter la boucle imbriquĂ©e. C'est plus dĂ©licat, et nous pourrions Ă©ventuellement le faire pour n'importe quelle statistique, nous devons donc supprimer ces statistiques Ă  un moment donnĂ©.

@jangorecki intéressant merci. Cela signifie que je vais continuer à utiliser tsibble pour intégrer... DATA.TABLES dans un tibble ! époustouflant :D

J'ai essayé d'utiliser frollmean pour calculer une "courbe logistique" non paramétrique qui montre P[y | x] pour le binaire y utilisant les voisins les plus proches de x . A été surpris que y stocké en tant que logical n'ait pas été converti automatiquement en integer :

DT = data.table(x = rnorm(1000), y = runif(1000) > .5)
DT[order(x), .(x, p_y = frollmean(y, 50L))]

Erreur dans froll(fun = "mean", x = x, n = n, fill = fill, algo = algo, align = align, :
x doit ĂȘtre de type numĂ©rique

Un exemple de la façon dont les arguments vectorisés x / n peuvent avoir un impact sur les performances.
https://github.com/AdrianAntico/RemixAutoML/commit/d8370712591323be01d0c66f34a70040e2867636#r34784427
moins de boucles, code plus facile à lire, beaucoup plus rapide (accélération 10x-36x).

prĂȘt pour frollapply : https://github.com/Rdatatable/data.table/pull/3600

    ### fun             mean     sum  median
    # rollfun          8.815   5.151  60.175
    # zoo::rollapply  34.373  27.837  88.552
    # zoo::roll[fun]   0.215   0.185      NA
    # frollapply       5.404   1.419  56.475
    # froll[fun]       0.003   0.002      NA

salut les gars, est-ce que FUN (dĂ©fini par l'utilisateur) transmis Ă  frollapply sera modifiĂ© pour renvoyer un objet R ou data.frame (data.table), x transmis Ă  frollapply pourrait ĂȘtre data.table de caractĂšre non contraint en numĂ©rique, alors FUN pourrait le faire labels et frollapply renvoient une liste ? Ensuite, nous pouvons effectuer des tests de rĂ©gression ou de roulement, comme les tests de Benford ou le rĂ©sumĂ© sur les Ă©tiquettes.

Il est toujours utile de fournir un exemple reproductible. Pour clarifier... dans un tel scĂ©nario, vous voudriez frollapply(dt, 3, FUN) renvoyer une liste de longueur nrow(dt) oĂč chaque Ă©lĂ©ment de la liste sera data.table renvoyĂ© par FUN(dt[window]) ?
frollapply(x=dt, n=3, fun=FUN)[[3]] Ă©quivaut Ă  FUN(dt[1:3])
frollapply(x=dt, n=3, FUN=FUN)[[4]] Ă©quivaut Ă  FUN(dt[2:4])
Est-ce exact? @jerryfuyu0104

Actuellement, nous prenons en charge plusieurs colonnes passées au premier argument, mais nous les traitons séparément, en boucle. Nous aurions probablement besoin d'un argument supplémentaire multi.var=FALSE , lorsqu'il est défini sur true, il ne bouclerait pas sur x (comme il le fait maintenant : list(FUN(x[[1]]),FUN(x[[2]])) ) mais transmettrait toutes les colonnes FUN(x) .

une mise Ă  jour pour cela?

J'appuie cette demande précédente.

De plus, serait-il possible de soutenir un argument « partiel » pour autoriser des fenĂȘtres partielles ?

@eliocamp pouvez-vous prĂ©ciser ce qu'est une fenĂȘtre partial ?

@eliocamp il serait possible de soutenir l'argument "partiel". Vous le savez peut-ĂȘtre dĂ©jĂ , mais la prise en charge de cette fonctionnalitĂ© existe dĂ©jĂ , en utilisant l'argument adaptive=TRUE , voir les exemples pour plus de dĂ©tails.

Cela signifierait calculer la fonction du dĂ©but Ă  la fin au lieu de former le point de la demi-fenĂȘtre.
Par exemple, pour une moyenne mobile de largeur 11, le premier élément renvoyé serait la moyenne des éléments 1 à 6. Le second, la moyenne du 1er au 7e, et ainsi de suite.

@jangorecki oh merci, je ne le savais pas ! Je vérifierai.

D'accord, nous avons besoin d'un argument partiel, non seulement pour la commodité mais aussi pour la vitesse. adaptive=TRUE ajoute un surcoût.
Et oui, nous avons également besoin d'une régression glissante, donc de fournir plusieurs variables et de les appliquer à la fois, pas chacune séparément.
Il n'y a pas de mise Ă  jour sur l'Ă©tat de ceux-ci.

J'aimerais aider, mais mes compétences en C++ sont totalement inexistantes. :sweat: Pensez-vous que cela pourrait convenir aux débutants complets ?

Nous ne coderons pas en C++ mais en C. Oui, c'est un bon point de départ. J'ai fait exactement cela sur frollmean.

Je regarde le code et il semble intimidant. Mais je vous tiendrai au courant dans tous les cas.

Mais maintenant, pour une autre requĂȘte : frollmean(.SD) doit conserver les noms. Plus gĂ©nĂ©ralement, froll* doit conserver les noms si l'entrĂ©e est une liste avec des noms.

En tant qu'utilisateur frĂ©quent de data.table, je trouve extrĂȘmement utile d'avoir des fonctionnalitĂ©s « sensibles au temps », comme celles actuellement proposĂ©es dans le package tsibble . Malheureusement, ce paquet est dĂ©veloppĂ© autour de dplyr . Je me demande si une implĂ©mentation data.table pourrait ĂȘtre possible. Les fonctions de fenĂȘtre proposĂ©es dans ce numĂ©ro sont un sous-ensemble de ces fonctionnalitĂ©s.

@ywhcuhk Merci pour vos commentaires, je pensais en fait que ce problĂšme en demandait dĂ©jĂ  trop. La majeure partie de cela est bien couverte par un rouleau d' emballage encore lĂ©ger qui est trĂšs rapide. En ce qui concerne les autres fonctionnalitĂ©s, je suggĂšre de crĂ©er un nouveau problĂšme pour chaque fonctionnalitĂ© qui vous intĂ©resse, de sorte que la discussion pour savoir si nous voulons implĂ©menter/maintenir peut ĂȘtre dĂ©cidĂ©e pour chacune sĂ©parĂ©ment. Rien qu'en regardant le fichier readme de tstibble, je ne vois rien de nouveau qu'il offre...
Son titre est "Tidy Temporal Data Frames" mais il ne semble mĂȘme pas offrir de jointures temporelles.

Merci @jangorecki pour la rĂ©ponse. C'est peut-ĂȘtre un problĂšme dĂ©pendant du contexte. La structure de donnĂ©es avec laquelle je traite le plus souvent est connue sous le nom de « donnĂ©es de panneau », avec un identifiant et une heure. Si le programme est "conscient" de cette fonctionnalitĂ© de donnĂ©es, de nombreuses opĂ©rations, en particulier les opĂ©rations de sĂ©ries chronologiques, seront rendues trĂšs faciles. Pour quelqu'un qui connaĂźt STATA, ce sont les opĂ©rations basĂ©es sur tsset et xtset , telles que lead, lag, fill gap, etc. Je pense que "l'index" dans la data.table peut ĂȘtre amĂ©liorĂ© d'une maniĂšre ou d'une autre pour permettre de telles opĂ©rations.

Bien sĂ»r, ces opĂ©rations peuvent ĂȘtre effectuĂ©es dans des fonctions data.table comme shift et by . Je pensais juste que le index dans data.table avait beaucoup de potentiel Ă  explorer. Je suis d'accord que cela devrait appartenir Ă  un autre problĂšme. Mais je ne sais pas comment le dĂ©placer sans perdre les discussions ci-dessus...

Cette page vous a été utile?
0 / 5 - 0 notes