Bir Dizinin gerçek değeri belirsizdir. A.empty, a.bool (), a.item (), a.any () veya a.all () kullanın


367

Sonuç veri çerçevemi bir koşulla filtreleme konusunda sorun yaşıyorum or. Sonucumun 0.25'in üstünde ve -0.25'in altında olan dftüm sütun vardeğerlerini ayıklamasını istiyorum .

Aşağıdaki bu mantık bana belirsiz bir gerçek değeri veriyor, ancak bu filtrelemeyi iki ayrı işlemde böldüğümde işe yarıyor. Burada ne oluyor? önerilen nerede kullanılacağından emin değilim a.empty(), a.bool(), a.item(),a.any() or a.all().

 result = result[(result['var']>0.25) or (result['var']<-0.25)]

46
|yerine kullanınor
MaxU

1
İşte bir çözüm:abs(result['var'])>0.25
ColinMac

Yanıtlar:


566

orVe andpiton ifadeleri gerektiren truth-değerlerine. İçin pandasKullanmak "Bitsel" bu yüzden bu belirsiz olarak kabul edilir |(veya) ya da &operasyonları (ve):

result = result[(result['var']>0.25) | (result['var']<-0.25)]

Bunlar, bu tür veri yapıları için element olarak or(veya and) vermek üzere aşırı yüklenmiştir .


Bu ifadeye biraz daha açıklama eklemek için:

Eğer almak istediğinizde istisnası atılır boola pandas.Series:

>>> import pandas as pd
>>> x = pd.Series([1])
>>> bool(x)
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

Ne isabet operatör bir yerdi örtülü için işlenen dönüştürülür bool(kullandığınız orama aynı zamanda için olur and, ifve while):

>>> x or x
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> x and x
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> if x:
...     print('fun')
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
>>> while x:
...     print('fun')
ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

Bu 4 tabloların yanısıra bazı gizlemek birkaç piton işlevleri vardır bool(gibi aramaları any, all, filter, ...) bu normalde sorunlu değildir pandas.Seriesancak şeyiyle ben bu hatırlatmak istedik.


Sizin durumunuzda istisna gerçekten yararlı değildir, çünkü doğru alternatiflerden bahsetmez . İçin andve orşunları kullanabilirsiniz (öğe bazında karşılaştırmalar istiyorsanız):

  • numpy.logical_or:

    >>> import numpy as np
    >>> np.logical_or(x, y)

    veya sadece |operatör:

    >>> x | y
  • numpy.logical_and:

    >>> np.logical_and(x, y)

    veya sadece &operatör:

    >>> x & y

Operatörleri kullanıyorsanız , operatör önceliği nedeniyle parantezinizi doğru ayarladığınızdan emin olun .

Orada birkaç mantıksal numpy fonksiyonları olmalıdır üzerinde çalışmak pandas.Series.


İstisnada belirtilen alternatifler ifveya ile karşılaşırsanız daha uygundur while. Bunların her birini kısaca açıklayacağım:

  • Serinizin boş olup olmadığını kontrol etmek istiyorsanız :

    >>> x = pd.Series([])
    >>> x.empty
    True
    >>> x = pd.Series([1])
    >>> x.empty
    False

    Python normalde , açık bir boole yorumlaması yoksa lenkapların (örneğin ...) gth değerini doğru-değer olarak yorumlar. Python benzeri bir kontrol istiyorsanız, şunları yapabilirsiniz: veya yerine .listtupleif x.sizeif not x.emptyif x

  • Eğer senin Seriesiçeren bir ve yalnızca bir boolean değeri:

    >>> x = pd.Series([100])
    >>> (x > 50).bool()
    True
    >>> (x < 50).bool()
    False
  • Serinizin ilk ve tek öğesini kontrol etmek istiyorsanız ( .bool()boole içeriği olmasa bile çalışır):

    >>> x = pd.Series([100])
    >>> x.item()
    100
  • Eğer kontrol etmek istiyorsanız tüm veya herhangi bir öğe-boş değil ya-Yanlış değil sıfır şöyledir:

    >>> x = pd.Series([0, 1, 2])
    >>> x.all()   # because one element is zero
    False
    >>> x.any()   # because one (or more) elements are non-zero
    True

Bu python operatörleri neden panda serilerini işlemek için aşırı yüklenmiyor?
Mudit Jain

@MuditJain doğrudan aşırı yük için hiçbir yolu yoktur and, orve notPython. Bu işleçler bool, işlenenlerin döndürdüklerini doğrudan kullanır . Ve bir şekilde Pandas / NumPy ValueError, bu tür bir veri yapısının gerçek değerini belirsiz olarak değerlendirdikleri için zaten bunu yükseltmek için aşırı yüklendi .
MSeifert

çözüm tamam, ama açıklama iyi olmaktan uzak
blacksheep

2
@blacksheep Daha iyi açıklayabileceğim herhangi bir öneriniz var mı?
MSeifert

Harika bir açıklama. Aslında, daha soyut örneklerin yapamayacağı bir şekilde bitsel ve mantıklı olanı anlamama yardımcı oldu.
rocksNwaves

41

Boole mantığı için &ve tuşlarını kullanın |.

np.random.seed(0)
df = pd.DataFrame(np.random.randn(5,3), columns=list('ABC'))

>>> df
          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
2  0.950088 -0.151357 -0.103219
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.443863

>>> df.loc[(df.C > 0.25) | (df.C < -0.25)]
          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.443863

Ne olduğunu görmek için her karşılaştırma için bir boolean sütunu alırsınız, ör.

df.C > 0.25
0     True
1    False
2    False
3     True
4     True
Name: C, dtype: bool

Birden fazla ölçütünüz olduğunda, döndürülen birden çok sütun alırsınız. Bu nedenle birleştirme mantığı belirsizdir. Her sütunu ayrı ayrı kullanmak andveya orişlemek için öncelikle bu sütunu tek bir boole değerine indirmeniz gerekir. Örneğin, sütunların her birindeki değerin veya tüm değerlerin Doğru olup olmadığını görmek için.

# Any value in either column is True?
(df.C > 0.25).any() or (df.C < -0.25).any()
True

# All values in either column is True?
(df.C > 0.25).all() or (df.C < -0.25).all()
False

Aynı şeyi elde etmenin kıvrımlı bir yolu, tüm bu sütunları bir araya getirip uygun mantığı gerçekleştirmektir.

>>> df[[any([a, b]) for a, b in zip(df.C > 0.25, df.C < -0.25)]]
          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.443863

Daha fazla ayrıntı için dokümanlardaki Boole Dizine Ekleme konusuna bakın .


20

Pandalar bitsel kullanır '&' '|' ve her koşul bir '()' içine sarılmalıdır

Örneğin aşağıdaki çalışmaları

data_query = data[(data['year'] >= 2005) & (data['year'] <= 2010)]

Ancak uygun parantez olmadan aynı sorgu

data_query = data[(data['year'] >= 2005 & data['year'] <= 2010)]

8

Alternatif olarak, Operatör modülünü kullanabilirsiniz. Daha detaylı bilgi burada Python belgeleri

import operator
import numpy as np
import pandas as pd
np.random.seed(0)
df = pd.DataFrame(np.random.randn(5,3), columns=list('ABC'))
df.loc[operator.or_(df.C > 0.25, df.C < -0.25)]

          A         B         C
0  1.764052  0.400157  0.978738
1  2.240893  1.867558 -0.977278
3  0.410599  0.144044  1.454274
4  0.761038  0.121675  0.4438

1

Bu mükemmel cevap , neler olduğunu çok iyi açıklar ve bir çözüm sunar. Benzer durumlarda uygun başka bir çözüm eklemek istiyorum: queryyöntemi kullanarak :

result = result.query("(var > 0.25) or (var < -0.25)")

Ayrıca bkz . Http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-query .

(Şu anda üzerinde çalıştığım bir veri çerçevesi ile yapılan bazı testler, bu yöntemin booleans serilerinde bitsel operatörleri kullanmaktan biraz daha yavaş olduğunu gösteriyor: 2 ms vs. 870 µs)

Bir uyarı : Bunun basit olmadığı en az bir durum, sütun adlarının python ifadeleri olduğu durumdur. Ben sütunlar adında vardı WT_38hph_IP_2, WT_38hph_input_2ve log2(WT_38hph_IP_2/WT_38hph_input_2)ve aşağıdaki sorguyu gerçekleştirmek istedik:"(log2(WT_38hph_IP_2/WT_38hph_input_2) > 1) and (WT_38hph_IP_2 > 20)"

Aşağıdaki özel durum çağlayanını aldım:

  • KeyError: 'log2'
  • UndefinedVariableError: name 'log2' is not defined
  • ValueError: "log2" is not a supported function

Sorgu ayrıştırıcı üçüncü sütunun adıyla ifade tanımlamak yerine ilk iki sütun bir şey yapmaya çalışıyordu çünkü bu oldu sanırım.

Geçici bir önerilmiştir burada .


1

Aynı hatayla karşılaştım ve birkaç gün boyunca bir pyspark veri çerçevesi ile durdum , 2 alandan tamsayı değerlerini karşılaştırdığım için na değerlerini 0 ile doldurarak başarıyla çözebildim .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.