J'aime r mais certains problèmes sont tout simplement difficiles.
Le défi consiste à trouver la première instance d'une somme de roulement inférieure à 30 dans une série de temps irrégulière ayant une fenêtre à base de temps supérieure ou égale à 6 heures. J'ai un échantillon de la série p> nerveux n observations, il y a des intervalles N * (N-1) / 2 qui doivent être comparés. Par exemple, avec n = 2, il y a juste 1 intervalle pour évaluer. Pour n = 3, il y a 3 intervalles. Et ainsi de suite. P> Je suppose qu'il s'agit d'une variante du problème de somme sous-ensemble ( http : //fr.wikipedia.org/wiki/subset_sum_problem ) p> Bien que les données puissent être triées, je suppose que cela nécessite une solution de force brute testant chaque intervalle. P> L'aide serait appréciée. p> Edit: Voici les données avec la colonne DateTime formatée comme POSIXCT: P>
df <- structure(list(Person = structure(c(1L, 1L, 1L, 1L, 1L, 2L, 2L,
2L, 3L, 3L, 3L, 4L, 4L, 4L), .Label = c("A", "B", "C", "D"), class = "factor"),
DateTime = structure(c(1388560500, 1388564100, 1388566800,
1388571300, 1388582100, 1388560500, 1388567700, 1388600100,
1388559600, 1388563200, 1388580300, 1388556000, 1388560500,
1388582100), class = c("POSIXct", "POSIXt"), tzone = ""),
Value = c(5L, 5L, 5L, 5L, 5L, 25L, 25L, 2L, 20L, 5L, 1L,
1L, 13L, 15L)), .Names = c("Person", "DateTime", "Value"), row.names = c("1",
"2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13",
"14"), class = "data.frame")
3 Réponses :
J'ai trouvé que ceci soit un problème difficile dans R aussi. Donc j'ai fait un paquet pour cela!
require(data.table) setDT(df) df[ , roll := rollingByCalcs(df,dates="DateTime",target="Value", by="Person",stat=sum,lower=0,upper=6*60*60)] Person DateTime Value roll 1: A 2014-01-01 01:15:00 5 5 2: A 2014-01-01 02:15:00 5 10 3: A 2014-01-01 03:00:00 5 15 4: A 2014-01-01 04:15:00 5 20 5: A 2014-01-01 07:15:00 5 25 6: B 2014-01-01 01:15:00 25 25 7: B 2014-01-01 03:15:00 25 50 8: B 2014-01-01 12:15:00 2 2 9: C 2014-01-01 01:00:00 20 20 10: C 2014-01-01 02:00:00 5 25 11: C 2014-01-01 06:45:00 1 26 12: D 2014-01-01 00:00:00 1 1 13: D 2014-01-01 01:15:00 13 14 14: D 2014-01-01 07:15:00 15 28
+1, sympa! Pouvez-vous démontrer comment la sortie de votre fonction à l'aide des données d'échantillons de l'OP ressemblerait?
Chose sûre! @Dave M, pourriez-vous utiliser dput code> sur vos données? Ou pouvez-vous rendre vos données reproductibles en quelque sorte?
J'avais déjà créé les données, alors j'ai ajouté un dput à la question
Remarquable. Et très apprécié. Je ne suis pas au travail pour le moment, mais j'ai passé le week-end à rêver d'une solution - en vain. Les séquences ne sont pas aussi longues dans le jeu de données réel, mais il y a probablement 30 000 personnes à traiter. Je vais donc vous garder posté. Et merci beaucoup.
Chose sûre! Et si vous avez besoin d'une vitesse (et que vous exécutez Mac OSX ou Linux), vous pouvez modifier les noyaux de 1 à autant que vous le souhaitez.
Nous supposons qu'un intervalle est défini par deux rangées pour la même personne. Pour chaque personne, nous voulons le premier intervalle de ce type (sagesse) d'au moins 6 heures pour lesquels la somme de Ceci peut être représenté par une triple jointure dans SQL. La sélection interne choisit toutes les lignes constituées du début de l'intervalle ( donnant: p> xxx pré> de la valeur code> de ces deux rangées et de toutes les lignes intermédiaires est inférieure à 30. S'il y a plus de que l'un de ce premier intervalle pour une personne choisissez une arbitraire.
a.datetime code>), la fin de l'intervalle (
b.datetime code>) et des lignes entre eux (
C.DateTime code>) Regroupement par
Personne CODE> et intervalle et sommation sur la valeur
Code> à condition qu'il s'étend sur au moins 6
heures code>. La sélection externe ne conserve que ces lignes dont
total code> est personne code> ne conserve que celui dont celui dont
DateTime code> est le moins. S'il y a plus d'une première ligne (temps sage) pour une personne
code> il choisit un arbitrairement. P>
DF <- data.frame( Row = 1:14,
Person = structure(c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 4L,
4L, 4L), .Label = c("A", "B", "C", "D"), class = "factor"),
DateTime = structure(c(1388582100, 1388585700, 1388588400, 1388592900,
1388603700, 1388582100, 1388589300, 1388621700, 1388581200,
1388584800, 1388601900, 1388577600, 1388582100, 1388603700),
class = c("POSIXct", "POSIXt"), tzone = ""),
Value = c(5L, 5L, 5L, 5L, 5L, 25L, 25L, 2L, 20L, 5L, 1L, 1L, 13L, 15L) )
à partir de la version 1.9.8 (sur Cran 25 nov. 2016), le data.Table package a gagné la capacité de agrégée dans une jointure non équité em>. Person start end hours
1: A 2014-01-01 08:15:00 2014-01-01 14:15:00 6.00 hours
2: B 2014-01-01 08:15:00 2014-01-01 19:15:00 11.00 hours
3: B 2014-01-01 10:15:00 2014-01-01 19:15:00 9.00 hours
4: D 2014-01-01 07:00:00 2014-01-01 14:15:00 7.25 hours
5: D 2014-01-01 08:15:00 2014-01-01 14:15:00 6.00 hours