การทำความเข้าใจ inplace = True


109

ในpandasไลบรารีหลายครั้งมีตัวเลือกในการเปลี่ยนวัตถุ inplace เช่นด้วยคำสั่งต่อไปนี้ ...

df.dropna(axis='index', how='all', inplace=True)

ผมอยากรู้สิ่งที่จะถูกส่งกลับมาเช่นเดียวกับวิธีวัตถุที่มีการจัดการเมื่อถูกส่งผ่านไปเทียบกับเมื่อinplace=Trueinplace=False

การดำเนินการทั้งหมดมีการแก้ไขselfเมื่อinplace=Trueใด และเมื่อไหร่inplace=Falseที่วัตถุใหม่จะถูกสร้างขึ้นทันทีเช่นnew_df = selfแล้วnew_dfจะถูกส่งคืน?


14
ใช่inplace=Trueส่งNone inplace=Falseคืนสำเนาของวัตถุพร้อมกับการดำเนินการ เอกสารค่อนข้างชัดเจนในเรื่องนี้มีบางส่วนที่สับสนกับบางส่วนหรือไม่? SpeficallyIf True, do operation inplace and return None.
EdChum

ฉันกำลังคลาสย่อยอ็อบเจ็กต์ DataFrame และด้วยการดำเนินการเช่นการผสานดูเหมือนจะไม่สามารถทำได้ในสถานที่ ... self = self.merge(new_df, how='left', on='column2' ฉันไม่แน่ใจว่าจะสามารถกำหนดตัวเองใหม่ได้
Aran Freel

1
คุณถูกต้องที่DataFrame.mergeไม่มีinplaceอาร์กิวเมนต์ ส่งคืน DataFrame ดังนั้นจึงไม่มีปัญหาในการกำหนดใหม่
JAV

ใครสามารถเน้นข้อดีของการใช้มันในแง่ของการใช้ทรัพยากรได้ไหม
markroxor

2
@markroxor มีไม่มากจริงๆ ในบางกรณีinplaceการดำเนินการอาจเร็วขึ้นเล็กน้อยเนื่องจากคุณไม่จำเป็นต้องส่งคืนสำเนาของผลลัพธ์ แต่เกี่ยวกับมัน มีหลายเหตุผลที่จะไม่ใช้มัน
cs95

คำตอบ:


99

เมื่อinplace=Trueถูกส่งผ่านข้อมูลจะถูกเปลี่ยนชื่อตามเดิม (ไม่คืนค่าอะไรเลย) ดังนั้นคุณจะใช้:

df.an_operation(inplace=True)

เมื่อinplace=Falseถูกส่งผ่าน (นี่คือค่าเริ่มต้นดังนั้นจึงไม่จำเป็น) ดำเนินการและส่งคืนสำเนาของวัตถุดังนั้นคุณจะใช้:

df = df.an_operation(inplace=False) 

ฉันคิดinplaceถูกไหมที่คิดว่าเป็นเพียงตัวเลือกสำหรับวิธีการที่เปลี่ยนแปลงข้อมูลที่มีอยู่ แต่ไม่ใช่สำหรับวิธีการที่ 'ปรับรูปร่าง' ข้อมูลใหม่ ตัวอย่างเช่นฉันสามารถ. set_index (inplace = True) เนื่องจากใช้ค่ากับดัชนีที่มีอยู่ แต่ไม่สามารถ. reindex (inplace = True) ได้เนื่องจากสามารถสร้างแถวเพิ่มเติมบน DataFrame ที่ไม่มีอยู่ในอาร์เรย์ก่อนหน้า เหรอ?
24

4
วิธีนี้.dropna()ยอมรับinplace=Trueและสามารถปรับรูปร่างดาต้าเฟรมได้แน่นอนที่สุดจึงไม่
jorijnsmit

3
คุณต้องระวังตรงนี้ @ ac24 มีสิทธิมากหรือน้อย ในขณะที่dropnaส่งคืน dataframe ที่มีรูปร่างแตกต่างกัน แต่ก็ไม่ได้เปลี่ยนรูปร่างของข้อมูลพื้นฐาน แต่เพียงส่งคืนมาสก์ทับ (เมื่อinplace=False) ซึ่งอาจทำให้เกิดความกลัวSettingWithCopyWarningได้ เฉพาะเมื่อไม่มีการอ้างอิงถึงอาร์เรย์ของค่าเก่าอีกต่อไปแพนด้าจะเปลี่ยนรูปร่างตามมาสก์ กฎทั่วไปที่ดีกว่าคือ: inplaceพร้อมใช้งานเมื่อการดำเนินการไม่จำเป็นต้องจัดสรรค่าสำรองใหม่ของค่า
BallpointBen

49

ในหมีแพนด้า inplace = True ถือว่าเป็นอันตรายหรือไม่?

TLDR; ใช่ใช่แล้ว

  • inplaceตรงกันข้ามกับความหมายของชื่อมักจะไม่ป้องกันการสร้างสำเนาและ (เกือบ) ไม่เคยให้ประโยชน์ด้านประสิทธิภาพใด ๆ
  • inplace ใช้ไม่ได้กับวิธีการผูกมัด
  • inplace เป็นข้อผิดพลาดทั่วไปสำหรับผู้เริ่มต้นดังนั้นการลบตัวเลือกนี้จะทำให้ API ง่ายขึ้น

ผมไม่แนะนำให้ตั้งค่าพารามิเตอร์นี้มันมีจุดมุ่งหมายเพียงเล็กน้อย ดูปัญหา GitHubซึ่งเสนอว่าinplaceอาร์กิวเมนต์เลิกใช้งานทั่วทั้ง API

เป็นความเข้าใจผิดทั่วไปที่ว่าการใช้inplace=Trueจะทำให้โค้ดมีประสิทธิภาพหรือเหมาะสมมากขึ้น ในความเป็นจริงมีอย่างไม่มีผลประโยชน์inplace=Trueจากการใช้ ทั้งเวอร์ชันที่อยู่ในตำแหน่งและเวอร์ชันนอกสถานที่จะสร้างสำเนาของข้อมูลต่อไปโดยเวอร์ชันที่วางไว้จะกำหนดสำเนากลับโดยอัตโนมัติ

inplace=Trueเป็นข้อผิดพลาดทั่วไปสำหรับผู้เริ่มต้น ตัวอย่างเช่นสามารถทริกเกอร์SettingWithCopyWarning :

df = pd.DataFrame({'a': [3, 2, 1], 'b': ['x', 'y', 'z']})

df2 = df[df['a'] > 1]
df2['b'].replace({'x': 'abc'}, inplace=True)
# SettingWithCopyWarning: 
# A value is trying to be set on a copy of a slice from a DataFrame

การเรียกใช้ฟังก์ชันบนคอลัมน์ DataFrame โดยinplace=True อาจใช้หรือไม่ก็ได้ โดยเฉพาะอย่างยิ่งเมื่อเกี่ยวข้องกับการทำดัชนีที่ถูกล่ามโซ่

ถ้าเป็นปัญหาที่อธิบายไว้ข้างต้นไม่พอinplace=Trueยังเป็นอุปสรรคต่อการวิธีการผูกมัด ตัดกันการทำงานของ

result = df.some_function1().reset_index().some_function2()

ตรงข้ามกับ

temp = df.some_function1()
temp.reset_index(inplace=True)
result = temp.some_function2()

อดีตยืมตัวเองเพื่อการจัดระเบียบรหัสที่ดีขึ้นและความสามารถในการอ่าน


การอ้างสิทธิ์สนับสนุนอีกประการหนึ่งคือ API สำหรับset_axisเพิ่งมีการเปลี่ยนแปลงเมื่อไม่นานมานี้ทำให้inplaceค่าเริ่มต้นถูกเปลี่ยนจาก True เป็น False ดูGH27600 นักพัฒนาที่ยอดเยี่ยม!


1
แน่นอนว่าใช้inplace=Trueไม่ได้กับการผูกมัด ฯลฯ แต่ที่ชัดเจนคือคุณเข้าใจว่ามันทำอะไรในแนวความคิด โดยส่วนตัวแล้วฉันคิดว่ามันสะอาดกว่าเล็กน้อยในการหลีกเลี่ยงการมอบหมาย - คุณจะชอบลบlist.sortฯลฯ ออกจากไลบรารีมาตรฐานด้วยหรือไม่?
Chris_Rands

4
ฉันไม่คิดว่าเป็นการเปรียบเทียบที่ยุติธรรม มีประโยชน์ที่ชัดเจนบางประการของการใช้ list.sort และ sorted เช่นเดียวกันกับฟังก์ชันอื่น ๆ ในสถานที่ ไม่มีประโยชน์ที่แท้จริงที่นี่วิธีการผูกมัดเป็นเรื่องธรรมดามากในแพนด้าและมีแผนสำหรับการเลิกใช้อาร์กิวเมนต์นี้อยู่ดี
cs95

ฉันยังพบว่ามันสะอาดกว่าเล็กน้อยเพื่อหลีกเลี่ยงการมอบหมาย: ตัวอย่างเช่น python list.append()ยังอยู่ในสถานที่ในขณะที่แพนด้า df.append ไม่ได้ (และในไม่รองรับแม้แต่ inplace) ซึ่งทำให้ฉันหงุดหงิดไม่สิ้นสุด นี่คือเหตุผลที่ฉันต้องการทราบเพียงเพื่อทำความเข้าใจว่าประโยชน์ที่แท้จริงคืออะไร - ประโยชน์ที่ชัดเจนของการใช้ list.sort กับ sorted คืออะไรนอกเหนือจากการหลีกเลี่ยงการมอบหมายงาน มิฉะนั้นฉันคิดว่ามีประโยชน์อย่างแท้จริงที่นี่ - ฉันสามารถหลีกเลี่ยงงานมอบหมายได้ซึ่งโดยส่วนตัวแล้วฉันพบว่ามันอ่านง่ายกว่า
sdbbs

1
@sdbbs ต่อlist.append()ท้ายรายการที่มีอยู่ df.appendทำสำเนาข้อมูลของคุณ (ไม่ว่าคุณจะมี 5 แถวหรือ 5 ล้าน) จากนั้นเพิ่มแถวใหม่ในสำเนาของคุณแล้วส่งกลับ คุณคิดว่าอะไรเข้าท่ากว่ากัน? สำหรับ df.append, หลีกเลี่ยงให้มากที่สุด ฉันไม่คิดว่ามันเป็นตัวอย่างที่ดีในการโต้แย้งเรื่อง inplace = True ฉันไม่คิดว่าฟังก์ชันนั้นจะมีตำแหน่งใน API ด้วยซ้ำ
cs95

46

วิธีที่ฉันใช้ก็คือ

# Have to assign back to dataframe (because it is a new copy)
df = df.some_operation(inplace=False) 

หรือ

# No need to assign back to dataframe (because it is on the same copy)
df.some_operation(inplace=True)

สรุป:

 if inplace is False
      Assign to a new variable;
 else
      No need to assign

5
สวัสดี @ นาบินนั่นเป็นวิธีที่ชัดเจนเกินไปสำหรับทุกคนที่ทำงานกับนุ่นและนัมปี้ :-)
เวททริเวล PS

6

inplaceพารามิเตอร์:

df.dropna(axis='index', how='all', inplace=True)

ในPandasและวิธีการโดยทั่วไป:

1.หมีแพนด้าสร้างสำเนาของข้อมูลต้นฉบับ

2. ... ทำการคำนวณกับมัน

3. ... กำหนดผลลัพธ์ให้กับข้อมูลต้นฉบับ

4. ... ลบสำเนา

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

1.โค้ดของคุณจะดีบักได้ยากขึ้น (จริงๆแล้วSettingwithCopyWarningหมายถึงการเตือนคุณถึงปัญหาที่อาจเกิดขึ้น

2.ขัดแย้งกับวิธีการผูกมัด


มีกรณีที่เราควรใช้หรือยัง

ใช่แน่นอน หากเราใช้แพนด้าหรือเครื่องมือใด ๆ ในการจัดการกับชุดข้อมูลขนาดใหญ่เราสามารถเผชิญกับสถานการณ์ได้อย่างง่ายดายซึ่งข้อมูลขนาดใหญ่บางส่วนสามารถใช้หน่วยความจำทั้งหมดของเราได้ เพื่อหลีกเลี่ยงเอฟเฟกต์ที่ไม่ต้องการนี้เราสามารถใช้เทคนิคบางอย่างเช่นวิธีการผูกมัด :

(
    wine.rename(columns={"color_intensity": "ci"})
    .assign(color_filter=lambda x: np.where((x.hue > 1) & (x.ci > 7), 1, 0))
    .query("alcohol > 14 and color_filter == 1")
    .sort_values("alcohol", ascending=False)
    .reset_index(drop=True)
    .loc[:, ["alcohol", "ci", "hue"]]
)

ซึ่งทำให้โค้ดของเรามีขนาดกะทัดรัดมากขึ้น (แม้ว่าจะตีความและดีบักได้ยากขึ้นด้วย) และใช้หน่วยความจำน้อยลงเนื่องจากวิธีการผูกมัดทำงานร่วมกับค่าที่ส่งคืนของวิธีการอื่นจึงส่งผลให้มีสำเนาข้อมูลอินพุตเพียงชุดเดียว เราสามารถเห็นได้อย่างชัดเจนว่าเราจะมีการใช้หน่วยความจำข้อมูลเดิม 2 เท่าหลังจากการดำเนินการนี้

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


ข้อสรุปสุดท้าย:

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


2

บันทึกลงในตัวแปรเดียวกัน

data["column01"].where(data["column01"]< 5, inplace=True)

บันทึกลงในตัวแปรแยกต่างหาก

data["column02"] = data["column01"].where(data["column1"]< 5)

แต่คุณสามารถเขียนทับตัวแปรได้ตลอดเวลา

data["column01"] = data["column01"].where(data["column1"]< 5)

FYI: เป็นค่าเริ่มต้น inplace = False


1

เมื่อพยายามทำการเปลี่ยนแปลงกับดาต้าเฟรมของ Pandas โดยใช้ฟังก์ชันเราจะใช้ 'inplace = True' หากเราต้องการยืนยันการเปลี่ยนแปลงในดาต้าเฟรม ดังนั้นบรรทัดแรกในโค้ดต่อไปนี้จึงเปลี่ยนชื่อของคอลัมน์แรกใน 'df' เป็น 'Grades' เราจำเป็นต้องเรียกใช้ฐานข้อมูลหากต้องการดูฐานข้อมูลที่เป็นผลลัพธ์

df.rename(columns={0: 'Grades'}, inplace=True)
df

เราใช้ 'inplace = False' (นี่คือค่าเริ่มต้นด้วย) เมื่อเราไม่ต้องการกระทำการเปลี่ยนแปลง แต่เพียงพิมพ์ฐานข้อมูลผลลัพธ์ ดังนั้นสำเนาของฐานข้อมูลต้นฉบับที่มีการเปลี่ยนแปลงที่มุ่งมั่นจะถูกพิมพ์ออกมาโดยไม่แก้ไขฐานข้อมูลเดิม

เพื่อให้ชัดเจนยิ่งขึ้นรหัสต่อไปนี้จะทำสิ่งเดียวกัน:

#Code 1
df.rename(columns={0: 'Grades'}, inplace=True)
#Code 2
df=df.rename(columns={0: 'Grades'}, inplace=False}

0

inplace=True จะใช้ขึ้นอยู่กับว่าคุณต้องการเปลี่ยนแปลง df ดั้งเดิมหรือไม่

df.drop_duplicates()

จะทำการดูเฉพาะค่าที่ลดลง แต่ไม่ทำการเปลี่ยนแปลงใด ๆ กับ df

df.drop_duplicates(inplace  = True)

จะลดค่าและทำการเปลี่ยนแปลง df

หวังว่านี่จะช่วยได้ :)


0

inplace=Trueทำให้ฟังก์ชันไม่บริสุทธิ์ มันเปลี่ยน dataframe เดิมและส่งกลับ None ในกรณีนั้นคุณจะทำลายสายโซ่ DSL เนื่องจากฟังก์ชัน dataframe ส่วนใหญ่ส่งคืน dataframe ใหม่คุณจึงใช้ DSL ได้อย่างสะดวก ชอบ

df.sort_values().rename().to_csv()

การเรียกใช้ฟังก์ชันพร้อมinplace=Trueผลตอบแทนไม่มีและสายโซ่ DSL เสีย ตัวอย่างเช่น

df.sort_values(inplace=True).rename().to_csv()

จะโยน NoneType object has no attribute 'rename'

สิ่งที่คล้ายกับการจัดเรียงและการจัดเรียง build-in ของ python lst.sort()ส่งคืนNoneและsorted(lst)ส่งคืนรายการใหม่

โดยทั่วไปห้ามใช้inplace=Trueเว้นแต่คุณจะมีเหตุผลเฉพาะในการทำเช่นนั้น เมื่อคุณต้องเขียนโค้ดการกำหนดใหม่เช่นdf = df.sort_values()ลองแนบการเรียกฟังก์ชันในสายโซ่ DSL เช่น

df = pd.read_csv().sort_values()...

การให้รหัสการทำงานที่แน่นอนพร้อมการจัดรูปแบบที่เหมาะสมจะช่วยให้ผู้ใช้เข้าใจคำตอบของคุณได้เร็วขึ้น ขอให้คุณทำเช่นเดียวกัน. ฉันไม่ใช่ผู้เชี่ยวชาญเรื่องแพนด้าจึงไม่สามารถฟอร์แมตใหม่ให้คุณตอบได้ แต่ขอแนะนำอย่างยิ่ง
Anand Vaidya

0

เท่าที่ฉันมีประสบการณ์เกี่ยวกับแพนด้าฉันอยากจะตอบ

อาร์กิวเมนต์ 'inplace = True' ย่อมาจาก data frame ต้องทำการเปลี่ยนแปลงอย่างถาวรเช่น

    df.dropna(axis='index', how='all', inplace=True)

เปลี่ยน dataframe เดียวกัน (เนื่องจากแพนด้าตัวนี้ค้นหารายการ NaN ในดัชนีและลดลง) ถ้าเราพยายาม

    df.dropna(axis='index', how='all')

แพนด้าแสดงดาต้าเฟรมพร้อมการเปลี่ยนแปลงที่เราทำ แต่จะไม่แก้ไขดาต้าเฟรมเดิม 'df'


0

หากคุณไม่ได้ใช้ inplace = True หรือคุณใช้ inplace = False โดยพื้นฐานแล้วคุณจะได้รับสำเนากลับคืนมา

ตัวอย่างเช่น:

testdf.sort_values(inplace=True, by='volume', ascending=False)

จะปรับเปลี่ยนโครงสร้างด้วยข้อมูลที่เรียงลำดับจากมากไปหาน้อย

แล้ว:

testdf2 = testdf.sort_values( by='volume', ascending=True)

จะทำสำเนา testdf2 ค่าทั้งหมดจะเหมือนกัน แต่การเรียงลำดับจะกลับด้านและคุณจะมีอ็อบเจกต์อิสระ

จากนั้นให้คอลัมน์อื่นพูดว่า LongMA แล้วคุณทำ:

testdf2.LongMA = testdf2.LongMA -1

คอลัมน์ LongMA ใน testdf จะมีค่าดั้งเดิมและ testdf2 จะมีค่าที่แยกส่วน

สิ่งสำคัญคือต้องติดตามความแตกต่างเมื่อห่วงโซ่ของการคำนวณเติบโตขึ้นและสำเนาของดาต้าเฟรมมีวงจรชีวิตของตัวเอง


0

ใช่ในนุ่นเรามีหลายหน้าที่มีพารามิเตอร์แต่โดยปกติแล้วมันจะได้รับมอบหมายให้inplaceFalse

ดังนั้นเมื่อคุณdf.dropna(axis='index', how='all', inplace=False)คิดว่าคุณไม่ต้องการเปลี่ยนต้นฉบับDataFrameดังนั้นระบบจะสร้างสำเนาใหม่ให้คุณพร้อมกับการเปลี่ยนแปลงที่จำเป็นแทน

แต่เมื่อคุณเปลี่ยนinplaceพารามิเตอร์เป็นTrue

จากนั้นก็เทียบเท่ากับการพูดอย่างชัดเจนว่าฉันไม่ต้องการให้สำเนาใหม่DataFrameทำการเปลี่ยนแปลงในสิ่งที่กำหนดDataFrame

สิ่งนี้บังคับให้ล่าม Python ไม่สร้างไฟล์DataFrame

แต่คุณยังสามารถหลีกเลี่ยงการใช้inplaceพารามิเตอร์ได้โดยการกำหนดผลลัพธ์ใหม่ให้กับ orignal DataFrame

df = df.dropna(axis='index', how='all')

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