2017-06-29 2 views
2

Hier finden Sie die DatenrahmenRollen 3 Vormonaten mit einzigartigen zählt nach groupby in Pandas Datenrahmen

Date  Name  data 
01/01/2017 Alpha  A  
02/01/2017 Alpha  A 
03/01/2017 Alpha  B 
01/01/2017 Beta  A 
01/20/2017 Beta  D 
03/01/2017 Beta  C 
04/01/2017 Beta  C 
05/01/2017 Beta  B 

Erwartete Ausgabe:

Date  Name  data 
Jan 2017  Alpha  1  
Feb 2017  Alpha  1 
Mar 2017  Alpha  2 
Jan 2017  Beta  2 
Mar 2017  Beta  3 
Apr 2017  Beta  1 
May 2017  Beta  2 

ich für einzigartige Zählungen von „data“ Gruppe Suche nach " Name "auf 3-monatiger rollierender Basis. Betrachten Sie das Beispiel von "März 2017" und "Name" -> "Beta". Die betrachteten Monate sind also Januar 2017, Februar 2017, März 2017 für den Namen "Beta". Die eindeutige Zählung ist 3. Ähnlich für andere. Bitte beachten Sie, dass die Anzahl der "Daten" für diese 3 Monate einmalig sein sollte

Jede Hilfe wird geschätzt.

+0

Ich dachte, 'df.groupby ('Name') gelten (lambda x: x.resample ('M') .rolling (3) .nunique()) 'nach' pd.to_datetime ('Date') 'zuerst ... aber' .nunique() 'existiert dort nicht. Also habe ich einfach '.apply (lambda x: len (x.unique()))' direkt nach '.rolling (3)' versucht, aber es hat nur die ursprünglichen Daten (A, A, B, C) zurückgegeben im Gegensatz zu meinem Erwartung 3, die das Ergebnis von len ist (set (AABC)) ... es scheint, '.apply()' kann float nur unter rollendem Objekt behandeln. Ich werde auch die Lösung warten. – su79eu7k

+0

Richtig, das hat mich auch erwischt. Ich probiere ein bisschen herum, als zu rollen. –

+0

scheinbar 'pandas.rolling' kann keine Spannweiten verarbeiten, die keine feste Länge (wie Monate) haben. Selbst wenn 'df.sort_index(). Rolling ('3M'). Size()' (Datum als Index) ergibt 'ValueError: <3 * MonthEnds> ist eine nicht fixierte Frequenz' Also fürchte ich, dass Sie das tun müssen es durch Schleifen über die Monate in der Spalte "Datum" –

Antwort

1

Gruppe pro Monat und Name, unstack und Monat sampeln, so dass alle Monate vorhanden sind, und Sie erhalten eine Spalte pro Name

df2 = df.groupby([pd.TimeGrouper('M'), 'Name', ])['data'].apply(set).unstack().resample('M').sum() 

df2

Name  Alpha Beta 
Date   
2017-01-31 {A}  {A, D} 
2017-02-28 {A}  None 
2017-03-31 {B}  {C} 
2017-04-30 None {C} 
2017-05-31 None {B} 

Multiple Iterator

einige itertools Magie Iterieren mehrmals über die gleiche Spalte

.

Die eigentliche Arbeit

def get_unique_items_rolling(df, period): 
    for col_name, col in df2.iteritems(): 
     s = pd.Series() 
#   print(f'---{col_name}---') 
     for idx, *iterators in zip(col.index[period-1:], *multiple_iterator(col, period)): 
      result = set(itertools.chain.from_iterable(i for i in iterators if pd.notnull(i) and i)) 
#    print(idx, result) 
      s[idx] = result 
     yield col_name, s 

df3 = pd.DataFrame.from_items(get_unique_items_rolling(df2, period))

  Alpha Beta 
2017-03-31 {A, B} {A, D, C} 
2017-04-30 {A, B} {C} 
2017-05-31 {B}  {B, C} 

df3.stack().apply(len)

Date  Name 
2017-03-31 Alpha 2 
      Beta  3 
2017-04-30 Alpha 2 
      Beta  1 
2017-05-31 Alpha 1 
      Beta  2 
dtype: int64 
Verwandte Themen