ค่าความจริงของซีรี่ส์นั้นไม่ชัดเจน ใช้ a.empty, a.bool (), a.item (), a.any () หรือ a.all ()


366

มีปัญหาในการกรอง dataframe ผลลัพธ์โดยมีorเงื่อนไข ฉันต้องการผลลัพธ์ของฉันdfเพื่อแยกvarค่าคอลัมน์ทั้งหมดที่สูงกว่า 0.25 และต่ำกว่า -0.25

ตรรกะด้านล่างนี้ให้คุณค่าความจริงที่คลุมเครือกับฉัน แต่มันทำงานเมื่อฉันแยกตัวกรองนี้ออกเป็นสองการดำเนินการแยกกัน เกิดอะไรขึ้นที่นี่ ไม่แน่ใจว่าจะใช้ข้อเสนอแนะที่a.empty(), a.bool(), a.item(),a.any() or a.all()ใด

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

46
ใช้|แทนor
MaxU

1
นี่เป็นวิธีแก้ปัญหา:abs(result['var'])>0.25
ColinMac

คำตอบ:


566

orและandงูหลามงบต้องtruth-values สำหรับpandasสิ่งเหล่านี้ถือว่าไม่ชัดเจนดังนั้นคุณควรใช้การดำเนินการ "bitwise" |(หรือ) หรือ&(และ):

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

สิ่งเหล่านี้มากเกินไปสำหรับโครงสร้างข้อมูลประเภทนี้เพื่อให้เกิดองค์ประกอบที่ชาญฉลาดor(หรือand)


เพียงเพิ่มคำอธิบายเพิ่มเติมในข้อความนี้:

ข้อยกเว้นจะถูกโยนทิ้งเมื่อคุณต้องการได้รับ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().

สิ่งที่คุณตีเป็นสถานที่ที่ผู้ประกอบการโดยปริยายแปลงตัวถูกดำเนินการไปbool(คุณใช้orแต่ก็ยังเกิดขึ้นand, ifและ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().

นอกจากนี้งบ 4 มีฟังก์ชั่นหลามหลายอย่างที่ซ่อนบางboolสาย (เช่นany, all, filter, ... ) เหล่านี้โดยปกติไม่ได้มีปัญหากับpandas.Seriesแต่เพื่อความสมบูรณ์ที่ผมอยากจะพูดถึงเหล่านี้


ในกรณีของคุณยกเว้นไม่เป็นประโยชน์จริงๆเพราะมันไม่ได้พูดถึงทางเลือกที่เหมาะสม สำหรับandและorคุณสามารถใช้ (ถ้าคุณต้องการเปรียบเทียบองค์ประกอบที่ชาญฉลาด):

  • numpy.logical_or:

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

    หรือ|ผู้ประกอบการเพียง:

    >>> x | y
  • numpy.logical_and:

    >>> np.logical_and(x, y)

    หรือ&ผู้ประกอบการเพียง:

    >>> x & y

หากคุณกำลังใช้ประกอบการแล้วให้แน่ใจว่าคุณตั้งวงเล็บของคุณได้อย่างถูกต้องเพราะมีความสำคัญผู้ประกอบการ

มีหลายฟังก์ชั่น numpy ตรรกะซึ่งควรจะpandas.Seriesทำงานใน


ทางเลือกที่กล่าวถึงในข้อยกเว้นมีความเหมาะสมมากขึ้นถ้าคุณพบมันเมื่อทำหรือif whileฉันจะอธิบายสิ่งเหล่านี้ในไม่ช้า:

  • หากคุณต้องการตรวจสอบว่าซีรี่ส์ของคุณว่างเปล่าหรือไม่ :

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

    งูหลามปกติตีความlenGTH ของภาชนะบรรจุ (เช่นlist, tuple, ... ) เป็นค่าความจริงถ้ามันไม่เคยมีใครตีความบูลอย่างชัดเจน ดังนั้นหากคุณต้องการหลามเหมือนการตรวจสอบคุณสามารถทำ: if x.sizeหรือแทนif not x.emptyif x

  • หากคุณSeriesมีค่าบูลีนหนึ่งค่าเท่านั้น :

    >>> x = pd.Series([100])
    >>> (x > 50).bool()
    True
    >>> (x < 50).bool()
    False
  • หากคุณต้องการตรวจสอบรายการแรกและรายเดียวในซีรี่ส์ของคุณ (เช่น.bool()แต่ใช้ได้แม้กับเนื้อหาที่ไม่บูลีน):

    >>> x = pd.Series([100])
    >>> x.item()
    100
  • หากคุณต้องการตรวจสอบว่ารายการทั้งหมดหรือรายการใดไม่ใช่ศูนย์ไม่ว่างเปล่าหรือไม่ผิด:

    >>> 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

ทำไมตัวดำเนินการไพ ธ อนเหล่านี้จึงไม่โอเวอร์โหลดในการจัดการซีรีย์แพนด้า
Mudit Jain

@MuditJain ไม่มีทางเป็นไปได้โดยตรงเกินand, orและnotในหลาม ตัวดำเนินการเหล่านี้ใช้สิ่งที่boolอยู่บนตัวถูกดำเนินการส่งคืนโดยตรง และในทางที่ Pandas / NumPy โอเวอร์โหลดไปแล้วเพื่อยกระดับValueErrorเพราะพวกเขาพิจารณาถึงค่าความจริงของโครงสร้างข้อมูลที่คลุมเครือ
MSeifert

วิธีการแก้ปัญหาก็โอเค แต่คำอธิบายอยู่ไกลจากดี
blacksheep

2
@blacksheep คุณมีข้อเสนอแนะใด ๆ ที่ฉันจะอธิบายได้ดีขึ้นหรือไม่?
MSeifert

มันเป็นคำอธิบายที่ดี ที่จริงมันช่วยให้ฉันเข้าใจ bitwise vs logical ในแบบที่เป็นนามธรรมมากกว่าตัวอย่างล้มเหลวในการทำ
StonesNwaves

41

ตรรกะบูลีนการใช้งานและ&|

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

หากต้องการดูสิ่งที่เกิดขึ้นคุณจะได้รับคอลัมน์บูลีนสำหรับการเปรียบเทียบแต่ละครั้งเช่น

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

เมื่อคุณมีหลายเกณฑ์คุณจะได้รับผลตอบแทนหลายคอลัมน์ นี่คือเหตุผลที่ตรรกะการเข้าร่วมไม่ชัดเจน การใช้andหรือจัดการorแต่ละคอลัมน์แยกกันดังนั้นคุณต้องลดคอลัมน์นั้นเป็นค่าบูลีนเดี่ยวก่อน ตัวอย่างเช่นเพื่อดูว่าค่าใด ๆ หรือค่าทั้งหมดในแต่ละคอลัมน์เป็นจริงหรือไม่

# 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

วิธีการที่ซับซ้อนอย่างหนึ่งในการบรรลุสิ่งเดียวกันคือการซิปคอลัมน์ทั้งหมดเหล่านี้เข้าด้วยกันและดำเนินการตามตรรกะที่เหมาะสม

>>> 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

สำหรับรายละเอียดเพิ่มเติมอ้างถึงการจัดทำดัชนีบูลีนในเอกสาร


20

หมีแพนด้าใช้ bitwise '&' '|' และแต่ละเงื่อนไขควรอยู่ใน '()'

ตัวอย่างงานต่อไปนี้

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

แต่แบบสอบถามเดียวกันโดยไม่มีเครื่องหมายวงเล็บปีกกาที่เหมาะสมไม่ได้

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

8

หรืออีกวิธีหนึ่งคือคุณสามารถใช้โมดูลผู้ประกอบการ ข้อมูลรายละเอียดเพิ่มเติมอยู่ที่นี่เอกสาร Python

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

คำตอบที่ยอดเยี่ยมนี้อธิบายได้ดีว่าเกิดอะไรขึ้นและให้ทางออก ฉันต้องการเพิ่มโซลูชันอื่นที่อาจเหมาะสมในกรณีที่คล้ายกัน: ใช้queryวิธี:

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

ดูเพิ่มเติมhttp://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-query

(การทดสอบบางอย่างกับ dataframe ฉันกำลังทำงานกับแนะนำว่าวิธีนี้ช้ากว่าการใช้ตัวดำเนินการ bitwise ในชุดของ booleans: 2 ms เทียบกับ 870 )s)

คำเตือน : อย่างน้อยหนึ่งสถานการณ์ที่สิ่งนี้ไม่ตรงไปตรงมาคือเมื่อชื่อคอลัมน์เป็นนิพจน์หลาม ผมมีคอลัมน์ชื่อWT_38hph_IP_2, WT_38hph_input_2และlog2(WT_38hph_IP_2/WT_38hph_input_2)และต้องการที่จะดำเนินการค้นหาต่อไปนี้:"(log2(WT_38hph_IP_2/WT_38hph_input_2) > 1) and (WT_38hph_IP_2 > 20)"

ฉันได้รับข้อยกเว้นต่อไปนี้:

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

ฉันเดาว่าเกิดขึ้นเพราะตัวแยกวิเคราะห์ข้อความพยายามทำบางอย่างจากสองคอลัมน์แรกแทนที่จะระบุนิพจน์ด้วยชื่อของคอลัมน์ที่สาม

การแก้ปัญหาที่เป็นไปได้มีการเสนอที่นี่


1

ฉันพบข้อผิดพลาดเดียวกันและจนตรอกด้วย pyspark dataframe สองสามวันฉันสามารถแก้ไขได้สำเร็จโดยเติมค่า na ด้วย 0เนื่องจากฉันเปรียบเทียบค่าจำนวนเต็มจาก 2 ฟิลด์

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.