2009-12-23 1 views
1

J'ai une série chronologique de données dans TSV comme ceci:Compte tenu d'une série de temps pour d'ID uniques, j'ai besoin les 100 meilleurs deltas pour chaque période

ID \t Date \t Value 
------------------------------- 
1234567 \t 2009-01-01T00:00:00.000Z \t 121 
12131 \t 2009-06-01T00:00:00.000Z \t 151 
12131 \t 2009-07-01T00:00:00.000Z \t 15153 
... 

Il se glisse facilement dans la RAM, mais est trop grand pour Excel.

Il y a une valeur par mois et par ID, mais tous les ID n'ont pas d'entrées pour tous les 12 mois.

Les données s'étendent sur 12 mois, mais tous les ID n'ont pas tous les 12 mois. Je veux parcourir les données pour chaque ID, et s'il y a une entrée pour le mois précédent, prendre le mois en cours moins le mois précédent et le stocker dans une nouvelle colonne pour obtenir un delta. S'il n'y a pas d'entrée pour le mois précédent, puis retourner 0. Puis, pour chaque mois, je veux le top 100 positif et négatif de ces deltas, avec l'ID.

Je voudrais faire cela dans R, parce que c'est dur dans Excel et il continue à se bloquer. J'ai R, Rattle, etc. installé et j'ai travaillé à travers des exemples de base, mais ... la courbe d'apprentissage est raide. Je serais vraiment reconnaissant de l'aide :)

Répondre

7

Commencez par ajouter dans tous les mois manquants:

all_combs <- expand.grid(
    ID = unique(data$ID), 
    Date = unique(data$Date)) 

data <- merge(data, all_combs, by = c("ID", "Date"), all = T) 
# Ensure data ordered by date 
data <- data[with(data, order(ID, Date)), ] 

Puis ajouter une colonne de deltas (calculée avec diff)

library(plyr) 
data <- ddply(data, "ID", transform, delta = c(NA, diff(Value))) 

Enfin, retirez les deltas manquantes , ordonnez par leur valeur et extrayez le haut et le bas 10 dans chaque groupe.

changed <- subset(data, !is.na(delta)) 
changed <- changed[with(changed, order(ID, delta)), ] 

# Select top 100 for each 
top10 <- ddply(changed, "ID", function(df) { 
rbind(head(df, 10), tail(df, 10)) 
}) 
+0

Merci, en cours d'exécution maintenant. L'étape: data <- ddply prend beaucoup de temps, j'espère que cela se terminera bientôt :) Les données d'origine étaient de 50 Mo ou plus, mais il a probablement été considérablement élargi en ajoutant les mois manquants. – rjurney

+0

i ♡ expand.grid –

1

Pseudo Code pour commencer:

For Each ID 
    If Previous month data Exists 
    compute Diff 
    Else diff = 0 
return diff 

For Each Month 
    Max 100 (Positive) 
    Min 100 (Negative) 

#Realish Code 
dataset$diff <- lappply(dataset,function(ID,month,value){IF dataset[month-1] = TRUE{value-(value[month-1]})}) 
#This gets tricky since you need to know the month and what the previous month is in a format you can test 
4

Ok, d'abord un peu de code pour générer des données de test. Cela fait 100 ID aléatoires et pour chacun choisit 20 mois à partir d'une période de 2 ans avec des valeurs aléatoires. La commande est ensuite mélangée pour plus de plaisir.

## Generate some IDs 
ids <- sample(1000, 100) 

## Generate the data 
data <- do.call(rbind, 
       lapply(ids, 
         function(id) 
         data.frame(ID = id, 
            Date = sample(as.Date(paste(rep(c(2008:2009), each=12), 
            1:12, 1, sep="-")), 
            20), 
            Value = sample(1000, 20)))) 

## Shuffle 
data <- data[sample(nrow(data), nrow(data)),] 

est ici à quoi il ressemble pour moi:

> head(data) 
     ID  Date Value 
1007 205 2008-07-01 235 
1391 840 2008-12-01 509 
918 278 2009-12-01 951 
1213 945 2009-03-01 842 
1369 766 2009-07-01 555 
798 662 2008-12-01 531 

Ok, maintenant nous allons itérer sur ID et trouvez le diff pour chaque mois pour chaque ID. Avant cela, convertissons le mois en nombre afin qu'il soit plus facile de prendre des différences (c'est un peu sale, est-ce que quelqu'un connaît une meilleure façon de faire de l'arithmétique sur les objets Date?). Cela ne vient year * 12 + month pour que fonctionne l'arithmétique normale:

data$Month <- as.POSIXlt(data$Date)$mon + as.POSIXlt(data$Date)$year * 12 

Maintenant calculer les différences:

by.id <- by(data, data$ID, function(x) { 
    ## Sort by month. 
    x <- x[order(x$Month),] 
    ## Compute the month and value differences, taking care to pad the edge case. 
    data.frame(ID=x$ID, 
      Date = x$Date,    
      Month.diff=c(0, diff(x$Month)), 
      Value.diff=c(0,diff(x$Value))) 
}) 
by.id <- do.call(rbind, by.id) 

Voici ce que le résultat ressemble à:

> head(by.id) 
    ID  Date Month.diff Value.diff 
4.1 4 2008-02-01   0   0 
4.2 4 2008-03-01   1  123 
4.3 4 2008-05-01   2  -94 
4.4 4 2008-06-01   1  -243 
4.5 4 2008-08-01   2  -327 
4.6 4 2008-10-01   2  656 

Si la différence entre les mois consécutifs était supérieur à 1, alors les mois n'étaient pas adjacents et nous devrions mettre leurs valeurs à zéro.

by.id$Value.diff <- ifelse(by.id$Month.diff == 1, 
          by.id$Value.diff, 
          0) 

Enfin, nous itérer par mois et prendre les différences de N supérieur et inférieur (je vais mettre N à 10 ici au lieu de 100 depuis mon ensemble de données de test est assez faible).

by.month <- by(by.id, by.id$Date, function(x) { 
    ## Sort the data in each month 
    x <- x[order(x$Value.diff),] 
    ## Take the top and bottom and label them accordingly. 
    cbind(rbind(head(x, 10), tail(x, 10)), 
     type=rep(c("min", "max"), each=10)) 
}) 

Et là nous l'avons.Voici un résultat exemple:

> by.month[[24]] 
     ID  Date Month.diff Value.diff type 
130.20 130 2009-12-01   1  -951 min 
415.20 415 2009-12-01   1  -895 min 
662.20 662 2009-12-01   1  -878 min 
107.20 107 2009-12-01   1  -744 min 
824.20 824 2009-12-01   1  -731 min 
170.20 170 2009-12-01   1  -719 min 
502.20 502 2009-12-01   1  -714 min 
247.20 247 2009-12-01   1  -697 min 
789.20 789 2009-12-01   1  -667 min 
132.20 132 2009-12-01   1  -653 min 
64.20 64 2009-12-01   1  622 max 
82.20 82 2009-12-01   1  647 max 
381.20 381 2009-12-01   1  698 max 
303.20 303 2009-12-01   1  700 max 
131.20 131 2009-12-01   1  751 max 
221.20 221 2009-12-01   1  765 max 
833.20 833 2009-12-01   1  791 max 
806.20 806 2009-12-01   1  806 max 
780.20 780 2009-12-01   1  843 max 
912.20 912 2009-12-01   1  929 max 
Questions connexes