Pandas วิธีกรองซีรีส์


94

ฉันมีซีรี่ส์แบบนี้หลังจากทำ groupby ('name') และใช้ฟังก์ชัน mean () ในคอลัมน์อื่น

name
383      3.000000
663      1.000000
726      1.000000
737      9.000000
833      8.166667

ใครช่วยแสดงวิธีกรองแถวที่มีค่าเฉลี่ย 1.000000 หน่อยได้ไหม ขอขอบคุณและขอขอบคุณอย่างยิ่งในความช่วยเหลือของคุณ


คุณจะกรองซีรีส์ตามเงื่อนไขที่กำหนดได้อย่างไร?

คำตอบ:


127
In [5]:

import pandas as pd

test = {
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
}

s = pd.Series(test)
s = s[s != 1]
s
Out[0]:
383    3.000000
737    9.000000
833    8.166667
dtype: float64

10
ฉันชอบคำตอบด้านล่างเพราะสามารถถูกล่ามโซ่ได้ (กล่าวคือไม่จำเป็นต้องกำหนดsแล้วใช้สองครั้งในนิพจน์) ใช้ได้กับแพนด้า 0.18 เท่านั้น
IanS

ยังเห็นการเปรียบเทียบระยะเวลาใน piRSquared ของคำตอบ
IanS

63

จากแพนด้าเวอร์ชัน 0.18+ การกรองซีรีส์สามารถทำได้ดังนี้

test = {
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
}

pd.Series(test).where(lambda x : x!=1).dropna()

ชำระเงิน: http://pandas.pydata.org/pandas-docs/version/0.18.1/whatsnew.html#method-chaininng-improvements


3
ดีกว่ามากด้วยวิธีการผูกมัด (และทำให้ฉันนึกถึง Spark)
Dylan Hogg

จริง แต่ Spark ทำสิ่งที่เข้าใจง่ายกว่าในกรณีนี้คือกำจัดแถวที่ไม่ตรงกับเพรดิเคตนั่นหมายความว่าจะไม่ใช้ส่วน ".dropna ()" ซึ่งดูเหมือนจะไม่จำเป็นสำหรับฉันอย่างเห็นได้ชัดจนกว่าฉันจะอ่านเอกสาร โดนกัด
ซะแล้ว

44

ดังที่DACW ชี้ให้เห็นมีการปรับปรุงวิธีการผูกมัดในแพนด้า 0.18.1 ที่ทำในสิ่งที่คุณกำลังมองหาได้เป็นอย่างดี

แทนที่จะใช้.whereคุณสามารถส่งผ่านฟังก์ชันของคุณไปยัง.locตัวทำดัชนีหรือตัวสร้างดัชนีซีรีส์[]และหลีกเลี่ยงการเรียกไปที่.dropna:

test = pd.Series({
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
})

test.loc[lambda x : x!=1]

test[lambda x: x!=1]

พฤติกรรมที่คล้ายกันได้รับการสนับสนุนบนคลาส DataFrame และ NDFrame


2
นี่เป็นคำตอบที่ฉันชอบและดูเหมือนว่าจะเร็วที่สุดโดยไม่ต้องลงไปที่ตัวเลข (ดูการเปรียบเทียบเวลา)
IanS

21

วิธีที่รวดเร็วในการทำเช่นนี้คือการสร้างใหม่โดยใช้numpyเพื่อแบ่งอาร์เรย์ที่อยู่ข้างใต้ ดูเวลาด้านล่าง

mask = s.values != 1
pd.Series(s.values[mask], s.index[mask])

0
383    3.000000
737    9.000000
833    8.166667
dtype: float64

เวลาที่ไร้เดียงสา

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


, ฉันชอบวิธีการของคุณฉันอยากรู้ว่าถ้าฉันมีหลายหน้ากาก Thx
Menglong Li

1
@MenglongLi ขึ้นอยู่กับคุณควรถามคำถาม เป็นไปได้มากว่าคุณจะรวมเข้ากับ & mask = mask1 & mask2
piRSquared

6

อีกวิธีหนึ่งคือการแปลงเป็น DataFrame ก่อนและใช้วิธีการสืบค้น (สมมติว่าคุณติดตั้ง numexpr):

import pandas as pd

test = {
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
}

s = pd.Series(test)
s.to_frame(name='x').query("x != 1")

ฉันไม่คิดว่าจะผ่านเงื่อนไขเป็นสตริง
SzymonPajzert

1
สิ่งนี้จะเพิ่มค่าใช้จ่ายทั้งหมดของดาต้าเฟรมและจะช้ามาก
fantabolous

5

หากคุณชอบการทำงานแบบผูกมัดคุณสามารถใช้compressฟังก์ชัน:

test = pd.Series({
383:    3.000000,
663:    1.000000,
726:    1.000000,
737:    9.000000,
833:    8.166667
})

test.compress(lambda x: x != 1)

# 383    3.000000
# 737    9.000000
# 833    8.166667
# dtype: float64

1

ในกรณีของฉันฉันมีซีรีส์แพนด้าที่มีค่าเป็นตัวละคร :

Out[67]
0    (H, H, H, H)
1    (H, H, H, T)
2    (H, H, T, H)
3    (H, H, T, T)
4    (H, T, H, H)

ดังนั้นฉันสามารถใช้การจัดทำดัชนีเพื่อกรองชุด applyแต่เพื่อสร้างดัชนีที่ฉันต้องการ เงื่อนไขของฉันคือ "ค้นหาสิ่งทอทั้งหมดที่มีตัว 'H' เพียงตัวเดียว

series_of_tuples[series_of_tuples.apply(lambda x: x.count('H')==1)]

ฉันยอมรับว่ามันไม่ใช่ "chainable" (เช่นสังเกตว่าฉันทำซ้ำseries_of_tuplesสองครั้งคุณต้องจัดเก็บชุดชั่วคราวใด ๆ ลงในตัวแปรเพื่อให้คุณสามารถเรียกใช้ (... ) ได้)

นอกจากนี้ยังอาจมีวิธีการอื่น ๆ (นอกจากนี้.apply(...)) ซึ่งสามารถใช้งานองค์ประกอบเพื่อสร้างดัชนีบูลีน

คำตอบอื่น ๆ อีกมากมาย (รวมถึงคำตอบที่ยอมรับ) โดยใช้ฟังก์ชัน chainable เช่น:

  • .compress()
  • .where()
  • .loc[]
  • []

สิ่งเหล่านี้ยอมรับ callables (lambdas) ซึ่งใช้กับ Seriesไม่ใช่กับค่าแต่ละค่าในชุดเหล่านั้น!

ดังนั้น Series of tuples ของฉันจึงทำงานแปลก ๆ เมื่อฉันพยายามใช้เงื่อนไขข้างต้น / callable / lambda กับฟังก์ชัน chainable ใด ๆ เช่น.loc[]:

series_of_tuples.loc[lambda x: x.count('H')==1]

สร้างข้อผิดพลาด:

KeyError: 'ระดับ H ต้องเหมือนกับชื่อ (ไม่มี)'

ฉันสับสนมาก แต่ดูเหมือนว่าจะใช้ฟังก์ชันSeries.countseries_of_tuples.count(...)ซึ่งไม่ใช่สิ่งที่ฉันต้องการ

ฉันยอมรับว่าโครงสร้างข้อมูลทางเลือกอาจดีกว่า:

  • ประเภทข้อมูลประเภท?
  • Dataframe (แต่ละองค์ประกอบของทูเปิลกลายเป็นคอลัมน์)
  • ชุดของสตริง (เพียงแค่เชื่อมสิ่งที่ถูกทับเข้าด้วยกัน):

สิ่งนี้จะสร้างชุดของสตริง (เช่นโดยการต่อทูเพิลการรวมอักขระในทูเพิลในสตริงเดียว)

series_of_tuples.apply(''.join)

ดังนั้นฉันจึงสามารถใช้chainable ได้Series.str.count

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