2014-12-22 22 views
8

kendin için deneyin:Neden DataFrame.loc [[1]] 1,800x df.ix [[1]] 'dan daha düşük ve df.loc [1]' den 3.500x daha yavaş?

import pandas as pd 
s=pd.Series(xrange(5000000)) 
%timeit s.loc[[0]] # You need pandas 0.15.1 or newer for it to be that slow 
1 loops, best of 3: 445 ms per loop 

Güncelleme: muhtemelen ağustos 2014 ya da öylesine içinde 0.15.1 tanıtıldı a legitimate bug in pandas olduğunu. Geçici çözümler: pandaların eski bir sürümünü kullanırken yeni bir sürüm beklemek; son teknoloji ürünü devir almak github sürümü; el ile pandas sürümünüzde tek satırlık bir değişiklik yapın; geçici olarak .loc yerine .ix kullanın.

I 4,8 milyon satır ile DataFrame sahiptir ve (a tek öğeli listesi ile) .iloc[[ id ]] kullanılarak tek bir satır özdeş .ix[[ id ]] daha 1,800x kat daha yavaş 489 ms, yaklaşık yarım saniye alır seçilmesi ve 3.500x kat daha yavaş.iloc[id] (kimliği bir değer olarak değil, bir liste olarak geçirerek). Adil olmak gerekirse, .loc[list] listenin uzunluğu ne olursa olsun, aynı zamanda yaklaşık zaman alır, ama ben 489 ms, özellikle .ix bin kez daha hızlı olduğu ve aynı sonucu üretir zaman harcamak istemiyorum. Benim anlayışım .ix'un daha yavaş olmasıydı, değil mi?

Pandalar kullanıyorum 0.15.1. Indexing and Selecting Data'daki mükemmel öğretici, 'un bir şekilde daha genel ve muhtemelen .loc ve .iloc'dan daha yavaş olduğunu gösterir. Özellikle, bir eksen tamsayı, SADECE etiket bazlı erişim ve değil konumsal erişim desteklenmektedir dayandığında, Ancak

söylüyor. Bu nedenle, bu tür durumlarda, genellikle 'un açık olması ve .iloc veya .loc kullanılması daha iyidir.

Burada kriterler ile bir ipython oturumdur:

print 'The dataframe has %d entries, indexed by integers that are less than %d' % (len(df), max(df.index)+1) 
    print 'df.index begins with ', df.index[:20] 
    print 'The index is sorted:', df.index.tolist()==sorted(df.index.tolist()) 

    # First extract one element directly. Expected result, no issues here. 
    id=5965356 
    print 'Extract one element with id %d' % id 
    %timeit df.loc[id] 
    %timeit df.ix[id] 
    print hash(str(df.loc[id])) == hash(str(df.ix[id])) # check we get the same result 

    # Now extract this one element as a list. 
    %timeit df.loc[[id]] # SO SLOW. 489 ms vs 270 microseconds for .ix, or 139 microseconds for .loc[id] 
    %timeit df.ix[[id]] 
    print hash(str(df.loc[[id]])) == hash(str(df.ix[[id]])) # this one should be True 
    # Let's double-check that in this case .ix is the same as .loc, not .iloc, 
    # as this would explain the difference. 
    try: 
     print hash(str(df.iloc[[id]])) == hash(str(df.ix[[id]])) 
    except: 
     print 'Indeed, %d is not even a valid iloc[] value, as there are only %d rows' % (id, len(df)) 

    # Finally, for the sake of completeness, let's take a look at iloc 
    %timeit df.iloc[3456789] # this is still 100+ times faster than the next version 
    %timeit df.iloc[[3456789]] 

Çıktı: Sorun pandalar 0.14 mevcut değilmiş gibi

The dataframe has 4826616 entries, indexed by integers that are less than 6177817 
df.index begins with Int64Index([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20], dtype='int64') 
The index is sorted: True 
Extract one element with id 5965356 
10000 loops, best of 3: 139 µs per loop 
10000 loops, best of 3: 141 µs per loop 
True 
1 loops, best of 3: 489 ms per loop 
1000 loops, best of 3: 270 µs per loop 
True 
Indeed, 5965356 is not even a valid iloc[] value, as there are only 4826616 rows 
10000 loops, best of 3: 98.9 µs per loop 
100 loops, best of 3: 12 ms per loop 
+0

Not numpy geçiş 'eşdeğer değildir. [id] 'bir dizi döndürecektir, ancak' [[id]] 'tek satırlı bir DataFrame döndürecektir. – BrenBarn

+0

@BrenBarn, evet, bu '.ix' için farkı açıklar: 141 µs vs 270 µs. Ama neden? .loc [[id]] 'çok yavaş? – osa

cevap

6

görünüyor. line_profiler ile profil oluşturdum ve sanırım ne olduğunu biliyorum. 0.15.1 pandalarından beri, belirli bir dizin yoksa KeyError yükseltilmiştir. .loc[list] sözdizimini kullandığınız zaman, bulunsa bile, tüm eksen boyunca bir dizin için kapsamlı bir arama yapıyor. Birincisi, bir elemanın bulunması durumunda erken bir sonlandırma yoktur ve ikincisi, bu durumda arama kaba kuvvettir.

File: .../anaconda/lib/python2.7/site-packages/pandas/core/indexing.py ,

1278              # require at least 1 element in the index 
    1279   1   241 241.0  0.1    idx = _ensure_index(key) 
    1280   1  391040 391040.0  99.9    if len(idx) and not idx.isin(ax).any(): 
    1281           
    1282               raise KeyError("None of [%s] are in the [%s]" % 
4

Pandalar indeksleme yavaş deli, bir dizine ekleme `[[kimlik]] ve` [id] kullanarak bu

df=pd.DataFrame(some_content) 
# takes forever!! 
for iPer in np.arange(-df.shape[0],0,1): 
    x = df.iloc[iPer,:].values 
    y = df.iloc[-1,:].values 
# fast!   
vals = np.matrix(df.values) 
for iPer in np.arange(-vals.shape[0],0,1): 
    x = vals[iPer,:] 
    y = vals[-1,:]