2016-08-29 2 views
3

Beispieldaten zusammenfassen:date Wert Änderungen identifizieren und die Daten mit sum() und diff() in R

product_id <- c("1000","1000","1000","1000","1000","1000", "1002","1002","1002","1002","1002","1002") 
    qty_ordered <- c(1,2,1,1,1,1,1,2,1,2,1,1) 
    price <- c(2.49,2.49,2.49,1.743,2.49,2.49, 2.093,2.093,2.11,2.11,2.11, 2.97) 
    date <- c("2/23/15","2/23/15", '3/16/15','3/16/15','5/16/15', "6/18/15", "2/19/15","3/19/15","3/19/15","3/19/15","3/19/15","4/19/15") 
    sampleData <- data.frame(product_id, qty_ordered, price, date) 

ich jedes Mal identifizieren möchte, wenn eine Änderung in einem Preis aufgetreten. Außerdem möchte ich die Gesamtmenge zwischen diesen beiden Preisänderungsdaten summieren. Beispiel: Für product_id == "1000" wurde der Preis am 16.03.15 von 2,49 auf 1,743 US-Dollar geändert. Die Gesamtmenge ist 1 + 2 + 1 = 4; der Unterschied zwischen diesen beiden frühesten Datum der Preisänderung ist von 23.02.15 bis 16.03.15, die 21 Tage ist.

der neuen Datenrahmen sollte also sein:

product_id sum_qty_ordered price date_diff 
1000   4   2.490    21 
1000   1   1.743   61 
1000   2   2.490   33 

Hier sind, was ich versucht habe:

** Hinweis: für diesen Fall eines einfachen „dplyr::group_by“ wird nicht funktionieren, da es ignoriert der Datumseffekt.

1) fand ich diesen Code aus Determine when columns of a data.frame change value and return indices of the change: Das ist jedes Mal zu identifizieren, wenn der Preis geändert, was das erste Datum zu identifizieren, wenn der Preis für jedes Produkt geändert.

IndexedChanged <- c(1,which(rowSums(sapply(sampleData[,3],diff))!=0)+1) 
sampleData[IndexedChanged,] 

Ich bin aber nicht sicher, wie die sum(qty_ordered) und das Datum Differenz für jeden dieser Einträge zu berechnen, wenn ich diesen Code verwenden.

2) Ich habe versucht, eine While-Schleife zu schreiben, um vorübergehend jede Charge von product_id, Preis, Datumsbereich (zB eine Untergruppe von Datenrahmen mit einem product_id, einem Preis, und alle Einträgen aus dem frühestmöglichen Zeitpunkt des Preises reichte ändere bis zum letzten Datum des Preises, bevor es sich geändert hat), und fasse dann diese Teilmenge zusammen, um die Summe (sum_qty_ordered) und das Datum diff zu erhalten. Allerdings denke ich, ich bin immer verwirrt von WHILE und FOR, also hat mein Code einige Probleme darin. Hier ist mein Code:

einen leeren Datenrahmen für die späteren Datenspeicher

NewData_Ready <- data.frame(
        product_id = character(), 
        price = double(), 
        early_date = as.Date(character()), 
        last_date=as.Date(character()), 
        total_qty_demanded = double(),       
        stringsAsFactors=FALSE) 

erstellen eine temporäre Tabelle erstellen, um die Batch-Preis, um Einträge zu speichern

temp_dataset <- data.frame(
        product_id = character(), 
        qty_ordered = double(), 
        price = double(), 
        date=as.Date(character()),         
        stringsAsFactors=FALSE) 

Schleife: Das ist chaotisch. ..und wahrscheinlich keinen Sinn, also helfe ich wirklich dabei.

Ich habe viel auf verwandten Fragen gesucht, aber ich habe nichts gefunden, die zu diesem Problem noch verwandt sind. Wenn Sie Vorschläge haben, lassen Sie es mich bitte wissen. Bitte geben Sie auch einige Vorschläge zur Lösung meiner Fragen. Ich würde Ihre Zeit und Hilfe sehr schätzen!

Here is my R version: 
platform  x86_64-apple-darwin13.4.0 
arch   x86_64      
os    darwin13.4.0     
system   x86_64, darwin13.4.0   
status          
major   3       
minor   3.1       
year   2016       
month   06       
day   21       
svn rev  70800      
language  R       
version.string R version 3.3.1 (2016-06-21) 
nickname  Bug in Your Hair  
+0

lesen Können Sie den Datumsunterschied mehr erklären? '21 60 94' scheint für die Beispielprodukt-ID nicht korrekt zu sein. –

+0

@PierreLafortune Für product_id "1000" zum Preis von $ 2.490, was ein Datum ist, das vom 23.02.15 (frühestens) bis zum 16.03.2015 (spätestes Datum, bevor der Preis auf 1,743 $ geändert wurde) lag. Das Datum zwischen dem 23.2. Und 15.3.16.15 beträgt also etwa 21 Tage. Dann gehe zum nächsten Preis für product_id "1000", und dieselbe Logik, um das Datum zu berechnen und bekam 61 Tage (Oops Typo oben) zwischen 3/16/15-5/16/15 und so weiter. Bitte lassen Sie mich wissen, wenn das Sinn macht. Danke für Ihre Hilfe!! – lemonC

+0

Aber es gab keine Preisänderung für '6/18/15'. Warum wurde '94' als Preisänderungslücke codiert wie in den anderen? –

Antwort

3

Mit data.table:

library(data.table) 
setDT(sampleData) 

Einige Preprocessing:

sampleData[, firstdate := as.Date(date, "%m/%d/%y")] 

Basierend auf, wie Sie Datum diff berechnen, sind wir besser dran, einen Datumsbereich für jede Zeile zu erstellen:

sampleData[, lastdate := shift(firstdate,type = "lead"), by = product_id] 
sampleData[is.na(lastdate), lastdate := firstdate] 
# Arun's one step: sampleData[, lastdate := shift(firstdate, type="lead", fill=firstdate[.N]), by = product_id] 

Dann eine neue ID für jede Preisänderung erstellen:

sampleData[, price_id := cumsum(c(0,diff(price) != 0)), by = product_id] 

dann Ihre groupwise Funktionen berechnen, durch Produkt- und Preis Lauf:

sampleData[, 
      .(
      price = unique(price), 
      sum_qty = sum(qty_ordered), 
      date_diff = max(lastdate) − min(firstdate) 
      ), 
      by = .(
      product_id, 
      price_id 
      ) 
      ] 

    product_id price_id price sum_qty date_diff 
1:  1000  0 2.490  4 21 days 
2:  1000  1 1.743  1 61 days 
3:  1000  2 2.490  2 33 days 
4:  1002  0 2.093  3 28 days 
5:  1002  1 2.110  4 31 days 
6:  1002  2 2.970  1 0 days 

ich die letzte Preisänderung denke für 1000 nur 33 Tage und der vorhergehende ist 61 (nicht 60). Wenn Sie den ersten Tag angeben, ist es 22, 62 und 34, und die Zeile sollte date_diff = max(lastdate) − min(firstdate) + 1

+0

vielen dank! Das ist perfekt für das, was ich will! Eine Frage, würde es Ihnen etwas ausmachen, diesen Code 'cumsum (c (0, diff (Preis)! = 0))' ein bisschen mehr bitte zu erklären? Ich weiß cumsum(), verstehe aber nicht ganz das diff() mit ungleich 0. – lemonC

+0

@lemonC Sicher: zuerst nehmen wir 'diff (price)', das den Unterschied zwischen allen Werten in einem Vektor berechnet. Mit "diff (Preis)! = 0" wandle ich dies in einen Vektor von "T/F" mit "TRUE" um, wenn der Preis unterschiedlich ist (d. H. Der Beginn einer neuen Gruppe). Ich verknüpfe dann Null mit dem Anfang von diesem, da diff 'n - 1' Werte in der Rückkehr gab. Dieser Schritt konvertiert auch die 'T/F's in' 1/0'. Jetzt habe ich einen Vektor mit 1 an jeder Position einer Preisänderung. Das "Cumsum" davon zu nehmen, erstellt eine Autoinkrement-ID für jede Gruppe. – Chris

+3

'shift (firstdate, type =" lead ")' kann in 'shift (firstdate, type =" lead ", fill = firstdate [.N])' geändert werden, so dass der nächste Schritt vermieden werden kann NA-Eintrag mit dem letzten Wert direkt. – Arun