2014-12-12 17 views
12

Uzun zamandır işimde kullanmış olduğum bir toplama işlevini kullanıyorum. Buradaki fikir, eğer işleve geçirilen dizinin uzunluğu 1 ise (yani, grubun sadece bir gözlemi varsa), o zaman gözlemler döndürülür. Dizinin uzunluğu birinden büyükse, gözlemler bir listede döndürülür.Pandas Groupby Agg İşlevi Azaltmıyor

Bu, bazıları için garip gelebilir, ancak bu bir X, Y problemi değil, bu soruyla alakalı olmayan bir şeyi yapmak için iyi bir nedenim var.

def MakeList(x): 
    """ This function is used to aggregate data that needs to be kept distinc within multi day 
     observations for later use and transformation. It makes a list of the data and if the list is of length 1 
     then there is only one line/day observation in that group so the single element of the list is returned. 
     If the list is longer than one then there are multiple line/day observations and the list itself is 
     returned.""" 
    L = x.tolist() 
    if len(L) > 1: 
     return L 
    else: 
     return L[0] 

Şimdi bazı nedenlerden dolayı, ben I üzerinde çalışıyorum geçerli veri seti ile olsun bir ValueError fonksiyonu azaltmak olmadığını belirten:

Bu

ben kullanıyorum fonksiyonudur. İşte bazı test verisi ve kalan kullanıyorum adım: Bu hata ayıklamak çalışırken

import pandas as pd 
DF = pd.DataFrame({'date': ['2013-04-02', 
          '2013-04-02', 
          '2013-04-02', 
          '2013-04-02', 
          '2013-04-02', 
          '2013-04-02', 
          '2013-04-02', 
          '2013-04-02', 
          '2013-04-02', 
          '2013-04-02'], 
        'line_code': ['401101', 
            '401101', 
            '401102', 
            '401103', 
            '401104', 
            '401105', 
            '401105', 
            '401106', 
            '401106', 
            '401107'], 
        's.m.v.': [ 7.760, 
           25.564, 
           25.564, 
           9.550, 
           4.870, 
           7.760, 
           25.564, 
           5.282, 
           25.564, 
           5.282]}) 
DFGrouped = DF.groupby(['date', 'line_code'], as_index = False) 
DF_Agg = DFGrouped.agg({'s.m.v.' : MakeList}) 

, ben çıkış gibiydi print L ve print x.index ve etkisiyle bir baskı beyanı koymak şöyle:

[7.7599999999999998, 25.564] 
Int64Index([0, 1], dtype='int64') 
[7.7599999999999998, 25.564] 
Int64Index([0, 1], dtype='int64') 

Bazı nedenlerden dolayı agg Serisi'ni iki kez işleve geçiriyormuş gibi görünüyor. Bildiğim kadarıyla bu hiç de normal değil ve muhtemelen fonksiyonumun azalmamasının nedeni.

Örneğin

böyle bir işlev yazarsanız:

def test_func(x): 
    print x.index 
    return x.iloc[0] 

Bu sorun olmadan çalışır ve baskı ifadeler şunlardır: Her grubun yalnızca bir kez aktarılmaya devam ettiğini gösterir

DF_Agg = DFGrouped.agg({'s.m.v.' : test_func}) 

Int64Index([0, 1], dtype='int64') 
Int64Index([2], dtype='int64') 
Int64Index([3], dtype='int64') 
Int64Index([4], dtype='int64') 
Int64Index([5, 6], dtype='int64') 
Int64Index([7, 8], dtype='int64') 
Int64Index([9], dtype='int64') 

Dizinin işlevi.

Bu sorunun neden başarısız olduğunu anlamama yardımcı olan var mı? Neden

+1

Bu sizin işlevi bazen bir liste ve bazen tek bir değeri verirse farklı dtypes bu iki durum için kullanılacak beri pandalar, karışır olması mümkündür. Bu şekilde yapmamak muhtemelen daha iyidir. İki kez çağıran davranış, "burada" (http://stackoverflow.com/questions/21390035/python-pandas-groupby-object-apply-method-duplicates-first-group) açıklanan sorunla ilgili olabilir. : Fonksiyonun mevcut veriyi değiştirip değiştirmediğini kontrol etmek için fonksiyonu ilk grupta iki kez çağırır. – BrenBarn

+0

Hmmm .... Belki nesne dtype olarak ayarlamayı denemeliyim. –

+0

En garip olan şey, bu kodu her zaman sorun olmaksızın yeniden kullanıyorum. Uyguladığım ve farklı veri paketlerini geçirdiğimi biliyorum, ki bu, devam eden baskı ifadelerinden emin olmak için oldukça zordur, ancak agh oldukça basittir. Hatayı yeniden oluşturdunuz mu? –

cevap

24

Gerçekten sana anlatamam ben ....

teşekkür çalışan birçok birçok veri setleri başarı ile bu fonksiyonu kullandık, ama benim deneyimlerinden listpandas.DataFrame tüm çalışmadığını iyi.

Genelde tuple kullanıyorum. çalışacak O:

def MakeList(x): 
    T = tuple(x) 
    if len(T) > 1: 
     return T 
    else: 
     return T[0] 

DF_Agg = DFGrouped.agg({'s.m.v.' : MakeList}) 

    date line_code   s.m.v. 
0 2013-04-02 401101 (7.76, 25.564) 
1 2013-04-02 401102   25.564 
2 2013-04-02 401103    9.55 
3 2013-04-02 401104    4.87 
4 2013-04-02 401105 (7.76, 25.564) 
5 2013-04-02 401106 (5.282, 25.564) 
6 2013-04-02 401107   5.282 
+3

yerine 'tuple (L)' döndürmek için' tuple' türünün değişmez olduğu ve bu yüzden 'yıkanabilir' ve 'liste' olmaması ile ilgilidir. –

+0

muhtemelen! Fakat kavramlar "toplanma" bakış açısından aynıdır, yani bir şeyin işe yaramayacağını tahmin etmenin bir yolu yoktur. Güzel yakalayış! – Ufos

6

Bu DataFrame bir misfeature olduğunu. Toplayıcı ilk grup için bir liste döndürürse, bahsettiğiniz hatayla başarısız olur; İlk grup için bir liste dışı (dizi olmayan) döndürürse, iyi çalışır. bozuk kod groupby.py içinde:

def _aggregate_series_pure_python(self, obj, func): 

    group_index, _, ngroups = self.group_info 

    counts = np.zeros(ngroups, dtype=int) 
    result = None 

    splitter = get_splitter(obj, group_index, ngroups, axis=self.axis) 

    for label, group in splitter: 
     res = func(group) 
     if result is None: 
      if (isinstance(res, (Series, Index, np.ndarray)) or 
        isinstance(res, list)): 
       raise ValueError('Function does not reduce') 
      result = np.empty(ngroups, dtype='O') 

     counts[label] = group.shape[0] 
     result[label] = res 

Bildirim o if result is None ve isinstance(res, list. Seçenekleriniz şunlardır:

  1. Sahte dışarı GroupBy().agg(), bu nedenle, ilk grup için bir liste görmez veya

  2. Toplama işlemini kendiniz yapın, yukarıdaki gibi bir kod kullanarak, ancak hatalı sınamadan yapın.

+0

diğer cevapta açıklandığı gibi 'tuple' gayet iyi çalışacaktır. Tam olarak yukarıdaki işlev, nesnenin bir "tuple" olup olmadığını kontrol etmez. Hata ya da bir özellik - siz karar verin! – Ufos