วิธีการตรวจสอบว่าคอลัมน์ Pandas มีค่าเฉพาะ


156

ฉันพยายามที่จะตรวจสอบว่ามีรายการในคอลัมน์นุ่นที่มีค่าเฉพาะ if x in df['id']ผมพยายามที่จะทำเช่นนี้กับ ฉันคิดว่านี้เป็นคนที่ทำงานยกเว้นเมื่อเราเลี้ยงมันคุ้มค่าที่ฉันรู้ไม่ได้อยู่ในคอลัมน์ก็ยังคงกลับมา43 in df['id'] Trueเมื่อฉันเซ็ตย่อยไปยังเฟรมข้อมูลที่มีรายการที่ตรงกับ id ที่หายไปdf[df['id'] == 43]เท่านั้นจะไม่มีรายการอยู่ในนั้น ฉันจะตรวจสอบได้อย่างไรว่าคอลัมน์ในกรอบข้อมูลของ Pandas มีค่าเฉพาะและทำไมวิธีการปัจจุบันของฉันจึงไม่ทำงาน (FYI ฉันมีปัญหาเดียวกันเมื่อฉันใช้งานในคำตอบนี้กับคำถามที่คล้ายกัน)

คำตอบ:


183

in ของซีรี่ส์ตรวจสอบว่าค่านั้นอยู่ในดัชนีหรือไม่:

In [11]: s = pd.Series(list('abc'))

In [12]: s
Out[12]: 
0    a
1    b
2    c
dtype: object

In [13]: 1 in s
Out[13]: True

In [14]: 'a' in s
Out[14]: False

ทางเลือกหนึ่งคือดูว่ามีค่าที่ไม่ซ้ำกันหรือไม่ :

In [21]: s.unique()
Out[21]: array(['a', 'b', 'c'], dtype=object)

In [22]: 'a' in s.unique()
Out[22]: True

หรือชุดหลาม:

In [23]: set(s)
Out[23]: {'a', 'b', 'c'}

In [24]: 'a' in set(s)
Out[24]: True

ตามที่ระบุโดย @DSM อาจมีประสิทธิภาพมากกว่า (โดยเฉพาะหากคุณเพิ่งทำสิ่งนี้เพื่อค่าหนึ่งค่า) เพื่อใช้กับค่าโดยตรง:

In [31]: s.values
Out[31]: array(['a', 'b', 'c'], dtype=object)

In [32]: 'a' in s.values
Out[32]: True

2
ฉันไม่ต้องการที่จะรู้ว่ามันไม่ซ้ำกันจำเป็นต้องส่วนใหญ่ฉันต้องการที่จะรู้ว่ามันมี
Michael

24
ฉันคิดว่า'a' in s.valuesน่าจะเร็วกว่าสำหรับซีรี่ส์ยาว
DSM

4
@AndyHayden คุณรู้หรือไม่ว่าทำไม'a' in sแพนด้าจึงเลือกที่จะตรวจสอบดัชนีมากกว่าค่าของซีรี่ส์หรือไม่ ในพจนานุกรมพวกเขาตรวจสอบกุญแจ แต่ชุดหมีแพนด้าควรทำตัวเหมือนรายการหรือแถวลำดับไม่ใช่หรือ?
Lei

3
เริ่มต้นจาก pandas 0.24.0 การใช้งานs.valuesและdf.valuesมีการแบ่งแยกสีสูง ดูนี่สิ นอกจากนี้s.valuesในบางกรณีช้ากว่าปกติมาก
Qusai Alothman

1
@QusaiAlothman ไม่มี.to_numpyหรือ.arrayมีอยู่ในซีรี่ส์ดังนั้นฉันจึงไม่แน่ใจเลยว่าพวกเขากำลังสนับสนุนอะไร (ฉันไม่ได้อ่าน "ท้อแท้") ในความเป็นจริงพวกเขากำลังจะบอกว่า .values อาจจะไม่กลับมาเป็นอาร์เรย์ numpy เช่นในกรณีของการที่เด็ดขาด ... แต่ที่ดีเป็นinจะยังคงทำงานตามที่คาดไว้ (ที่จริงมีประสิทธิภาพมากขึ้นว่ามันเป็นคู่อาร์เรย์ numpy)
แอนดี้เฮย์เดน

27

นอกจากนี้คุณยังสามารถใช้pandas.Series.isin ได้แม้ว่าจะยาวกว่า'a' in s.values:

In [2]: s = pd.Series(list('abc'))

In [3]: s
Out[3]: 
0    a
1    b
2    c
dtype: object

In [3]: s.isin(['a'])
Out[3]: 
0    True
1    False
2    False
dtype: bool

In [4]: s[s.isin(['a'])].empty
Out[4]: False

In [5]: s[s.isin(['z'])].empty
Out[5]: True

แต่วิธีการนี้สามารถยืดหยุ่นได้มากขึ้นถ้าคุณต้องการจับคู่ค่าหลายค่าพร้อมกันสำหรับ DataFrame (ดูDataFrame.isin )

>>> df = DataFrame({'A': [1, 2, 3], 'B': [1, 4, 7]})
>>> df.isin({'A': [1, 3], 'B': [4, 7, 12]})
       A      B
0   True  False  # Note that B didn't match 1 here.
1  False   True
2   True   True

คุณสามารถใช้ฟังก์ชัน DataFrame.any () :s.isin(['a']).any()
thando

17
found = df[df['Column'].str.contains('Text_to_search')]
print(found.count())

found.count()ประสงค์มีตัวเลขของการแข่งขัน

และถ้าเป็น 0 หมายความว่าไม่พบสตริงในคอลัมน์


2
ทำงานได้สำหรับฉัน แต่ฉันใช้ len (พบ) เพื่อรับจำนวน
kztd

1
ใช่ len (พบ) เป็นตัวเลือกที่ค่อนข้างดีกว่า
Shahir Ansari

1
วิธีการนี้ใช้ได้ผลสำหรับฉัน แต่ฉันต้องรวมพารามิเตอร์na=Falseและregex=Falseสำหรับกรณีการใช้งานของฉันตามที่อธิบายไว้ที่นี่: pandas.pydata.org/pandas-docs/stable/reference/api/ …
Mabyn

1
แต่ string.contain ทำการค้นหาสตริงย่อย ตัวอย่าง: หากมีค่าที่เรียกว่า "head_hunter" อยู่ ผ่าน "หัว" ในการจับคู่ str.contains และให้ True ซึ่งเป็นความผิด
karthikeyan

@karthikeyan มันไม่ผิดหรอก ขึ้นอยู่กับบริบทของการค้นหาของคุณ ถ้าคุณค้นหาที่อยู่หรือผลิตภัณฑ์ คุณจะต้องมีผลิตภัณฑ์ทั้งหมดที่พอดีกับคำอธิบาย
Shahir Ansari

6

ฉันทำแบบทดสอบง่ายๆสองสามข้อ:

In [10]: x = pd.Series(range(1000000))

In [13]: timeit 999999 in x.values
567 µs ± 25.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [15]: timeit x.isin([999999]).any()
9.54 ms ± 291 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [16]: timeit (x == 999999).any()
6.86 ms ± 107 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [17]: timeit 999999 in set(x)
79.8 ms ± 1.98 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [21]: timeit x.eq(999999).any()
7.03 ms ± 33.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [22]: timeit x.eq(9).any()
7.04 ms ± 60 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [24]: timeit 9 in x.values
666 µs ± 15.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

น่าสนใจไม่สำคัญว่าคุณจะค้นหา 9 หรือ 999999 ดูเหมือนว่าใช้เวลาในการใช้ไวยากรณ์เป็นเวลาเท่ากัน (ต้องใช้การค้นหาแบบไบนารี)

In [24]: timeit 9 in x.values
666 µs ± 15.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [25]: timeit 9999 in x.values
647 µs ± 5.21 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [26]: timeit 999999 in x.values
642 µs ± 2.11 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [27]: timeit 99199 in x.values
644 µs ± 5.31 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [28]: timeit 1 in x.values
667 µs ± 20.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

ดูเหมือนว่าการใช้ x.values ​​นั้นเร็วที่สุด แต่อาจมีวิธีที่งดงามกว่าในแพนด้า?


มันจะดีถ้าคุณเปลี่ยนลำดับของผลลัพธ์จากน้อยที่สุดเป็นใหญ่ที่สุด เยี่ยมมาก!
smm

4

หรือใช้Series.tolistหรือSeries.any:

>>> s = pd.Series(list('abc'))
>>> s
0    a
1    b
2    c
dtype: object
>>> 'a' in s.tolist()
True
>>> (s=='a').any()
True

Series.tolistทำรายการเกี่ยวกับ a Seriesและอีกอันหนึ่งที่ฉันเพิ่งได้รับบูลีนSeriesจากปกติSeriesแล้วตรวจสอบว่ามีTrueบูลอยู่ในบูลSeriesหรือไม่



1

ใช้

df[df['id']==x].index.tolist()

หากxมีอยู่idแล้วมันจะกลับรายการดัชนีที่มีอยู่อื่นจะให้รายการที่ว่างเปล่า



0

สมมติว่าคุณ dataframe ดูเหมือนว่า:

ป้อนคำอธิบายรูปภาพที่นี่

ตอนนี้คุณต้องการตรวจสอบว่าชื่อไฟล์ "80900026941984" มีอยู่ใน dataframe หรือไม่

คุณสามารถเขียน:

if sum(df["filename"].astype("str").str.contains("80900026941984")) > 0:
    print("found")
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.