2015-11-18 48 views
5

Yaklaşık 100 sütun ve 200000 veri satırı içeren bir pandas.DataFrame nesnesine sahibim. Bunu, true değerinin eşikten büyük olduğu anlamına gelen bir bool veri çerçevesine dönüştürmeye çalışıyorum. Yanlış, daha az olduğu anlamına gelir ve NaN değerleri korunur. Hiçbir NaN değer varsaNavi'leri pandalarla tutarak veri kümesi eşitsizlikleri

, yayınlanmaya benim için yaklaşık 60 ms gerekir:

df >= threshold 

Ama NaN'ler başa çalıştığınızda, aşağıdaki yöntemi (20 sn çalışır, ancak çok yavaş).

def func(x): 
    if x >= threshold: 
     return True 
    elif x < threshold: 
     return False 
    else: 
     return x 
df.apply(lambda x: x.apply(lambda x: func(x))) 

Daha hızlı bir yol var mı?

+0

deneyin bu hat ile 'func' yerine:' x Yok başka x' değilse x> = eşiği dönmek, daha hızlı olabilir. BTW neden iki lambda x' atadınız? 'df.apply (func)' hile yapacak. – DeepSpace

+0

@DeepSpace aynı süreyi aldı – jsignell

cevap

3

Sen yapabilirsiniz:

new_df = df >= threshold 
new_df[df.isnull()] = np.NaN 

Ama bu yöntemi uygulamak kullanarak alacak neyi farklıdır. Burada maskenizin NaN, 0.0 ve 1.0 içeren float dtype'ı vardır. Uygulamanızda, NaN, False ve True ile object dtype alırsınız.

Hiçbiri maske olarak kullanılmayacak çünkü istediğiniz şeyi alamayabilirsiniz. IEEE, herhangi bir NaN karşılaştırmasının False vermesi gerektiğini ve başvuru yönteminin NaN'yi iade ederek dolaylı olarak ihlal ettiğini söyler!

En iyi seçenek, NaN'leri ayrı ayrı takip etmektir ve darboğaz takıldığında df.isnull() oldukça hızlıdır.

+0

https: //pypi.python. org/pypi/Bottleneck –

1

Sen NaN'ler ayrı Bu yayını kullanarak kontrol edebilirsiniz:

df.isnull() | df >= threshold 

İki maskeleri yakın almaya bekleyebilirsiniz: Python - find integer index of rows with NaN in pandas

df.isnull() 

bit usulü kullanılarak veya df >= threshold ile isnull çıktısını birleştirin Hesaplamak ve birleştirmek için 200ms, ama bu Tamam olmak için 20s yeterince uzakta olmalıdır.

+0

Onları nasıl birleştireceğiniz hakkında fikirleriniz var mı? Benim de aşağı inmem gerektiğini düşündüğüm yol bu. – jsignell

+0

Güncelleme yanıtı. –

+0

Bu benim için çalışmadı. Ben python 2.7.1, pandalar 0.17.0 (genellikle kullandığım) denedim ve bir NotImplementedError aldım, sonra python 3.4.3, pandalar 0.17.0 denedim ve var: 'bitwise_or' giriş türü için desteklenmedi – jsignell

0

Bu durumda, aşağıdaki gibi kodlanmış bir dizi gösterge dizisi kullanıyorum: 0 = Yanlış, 1 = Doğru ve NaN = eksik. bool dtype içeren bir Pandas DataFrame'de eksik değerler bulunamaz ve Python bool ve float nesnelerinin bir karışımını tutan object dtype'a sahip bir DataFrame etkili değildir. Bu bize np.float64 dtype ile DataFrames kullanmaya götürür. numpy.sign(x - threshold), karşılaştırmanız için -1 = (x < eşiği), 0 = (x == eşiği) ve +1 = (x> eşiği) değerlerini verir; bu, sizin amaçlarınız için yeterince iyi olabilir, ancak gerçekten 0/1 kodlamasına ihtiyacınız varsa , dönüşüm yerinde yapılabilir. Aşağıdaki zamanlamaları bir 200K uzunluk dizisi x üzerinde şunlardır:

In [45]: %timeit y = (x > 0); y[pd.isnull(x)] = np.nan 
100 loops, best of 3: 8.71 ms per loop 

In [46]: %timeit y = np.sign(x) 
100 loops, best of 3: 1.82 ms per loop 

In [47]: %timeit y = np.sign(x); y += 1; y /= 2 
100 loops, best of 3: 3.78 ms per loop 
+0

Yukarıdaki üç yaklaşımın size dtype 'np.float64' ile bir DataFrame y verdiğinden ve tümünün NaN'leri koruduğundan bahsetmeliydim. İkinci yaklaşım, False/True için -1/1 kodlamasını ve diğerlerinin de 0/1 kodlamasını vermektedir. 'y = (1 + np.sign (x))/2' de rekabetçi. –

+0

Bu, tam olarak eşitlik olduğunda istediğiniz şeyi vermeyebilir. np.sign (x - eşik) '' x == eşiği' ise 0 olur, böylece son sonuçta x eşiği ise 0 olur. Eşitlik bir olasılıksa, 'y = (1 + np.sign (eps + x - eşik))/2' ile devam edebilirsiniz, burada eps = np.finfo (np.float64) .eps'. –

İlgili konular