วิธีการส่งคอลัมน์อื่นทั้งหมดเป็นอาร์กิวเมนต์ให้กับ pandas fillna ()


95

ฉันต้องการเติมค่าที่ขาดหายไปในคอลัมน์หนึ่งด้วยค่าจากคอลัมน์อื่นโดยใช้fillnaวิธีการ

(ฉันอ่านมาว่าการวนซ้ำในแต่ละแถวจะเป็นการฝึกที่ไม่ดีมากและการทำทุกอย่างในคราวเดียวจะดีกว่า แต่ฉันไม่สามารถหาคำตอบได้fillna)

ข้อมูลก่อน:

Day  Cat1  Cat2
1    cat   mouse
2    dog   elephant
3    cat   giraf
4    NaN   ant

ข้อมูลหลังจาก:

Day  Cat1  Cat2
1    cat   mouse
2    dog   elephant
3    cat   giraf
4    ant   ant

คำตอบ:


174

คุณสามารถระบุคอลัมน์นี้เพื่อfillna(ดูเอกสาร ) โดยจะใช้ค่าเหล่านั้นในดัชนีที่ตรงกันเพื่อเติม:

In [17]: df['Cat1'].fillna(df['Cat2'])
Out[17]:
0    cat
1    dog
2    cat
3    ant
Name: Cat1, dtype: object

7
ดี! ฉันไม่รู้ว่าfillnaต้องใช้ซีรีส์
Ami Tavory

1
ขอบคุณ! ฉันคิดว่าซีรีส์ต้องมีขนาดที่แน่นอนของจำนวนค่า NA
xav

นอกจากนี้ยังใช้ได้กับดาต้าเฟรมสำหรับแถวหลายคอลัมน์ คุณสมบัติของ Fillna นั้นมีประโยชน์มาก
Wertikal

19

คุณสามารถทำได้

df.Cat1 = np.where(df.Cat1.isnull(), df.Cat2, df.Cat1)

โครงสร้างโดยรวมบน RHS ใช้รูปแบบการประกอบจากpandasตำราอาหาร (ซึ่งจ่ายเพื่ออ่านไม่ว่าในกรณีใด ๆ ) เป็นเวอร์ชันเวกเตอร์ของa? b: c.


ไม่ใช่วิธีแก้ปัญหาที่ฉันใช้สำหรับปัญหานี้ แต่เป็นรูปแบบที่น่าสนใจมาก! ขอบคุณ!
xav

มีวิธีใช้สำหรับหลายคอลัมน์หรือไม่ เช่นถ้า df นี้มี cat1, cat2, cat3, cat4, cat5 และสมมติว่า cat5 ว่างเปล่า จะมีวิธีเติม cat5 ด้วยค่าจาก cat1 ไหมถ้า cat1 ว่างแล้วก็ cat2 ถ้า cat2 ว่างแล้ว cat3 เป็นต้น
user8322222

@ user8322222 ฉันมาสายแน่นอน แต่ถ้าใครมีคำถามนี้คุณสามารถทำ np ที่ซ้อนกันได้ทุกที่เช่นเดียวกับที่คุณทำในเซลล์ excel = np ที่ไหน (cond, val_true, np.where (cond, val_true, val_false), ).
Kaisar

คุณต้องการบอกว่านี่เป็นเพียงการกำหนดแพนด้าที่สร้างpd.DataFrame.fillna()ขึ้นใหม่ และฉันสงสัยว่าพฤติกรรมของมุมเคสอาจแตกต่างกันเช่นสำหรับความยาวของซีรีส์ที่ไม่ตรงกันจากเฟรมข้อมูลที่ต่างกัน: dfA ['Cat1'], dfB ['Cat2']
smci

8

เพียงใช้valueพารามิเตอร์แทนmethod:

In [20]: df
Out[20]:
  Cat1      Cat2  Day
0  cat     mouse    1
1  dog  elephant    2
2  cat     giraf    3
3  NaN       ant    4

In [21]: df.Cat1 = df.Cat1.fillna(value=df.Cat2)

In [22]: df
Out[22]:
  Cat1      Cat2  Day
0  cat     mouse    1
1  dog  elephant    2
2  cat     giraf    3
3  ant       ant    4

ขอบคุณสำหรับคำตอบ! อะไรเปลี่ยนไปใช้ value แทนวิธีการที่ joris อธิบาย?
xav

@xav valueเป็นพารามิเตอร์แรกดังนั้นjoris จึงทำสิ่งเดียวกัน ในขณะที่เขากล่าวว่าให้ดูที่เอกสาร
chrisaycock

ใช่ docstring ทำให้เข้าใจผิดเล็กน้อยตามที่methodระบุไว้ในตอนแรก
joris

7

pandas.DataFrame.combine_firstก็ใช้ได้เช่นกัน

(ข้อควรระวัง: เนื่องจาก "คอลัมน์ดัชนีผลลัพธ์จะรวมกันของดัชนีและคอลัมน์ที่เกี่ยวข้อง" คุณควรตรวจสอบดัชนีและคอลัมน์ที่ตรงกัน )

import numpy as np
import pandas as pd
df = pd.DataFrame([["1","cat","mouse"],
    ["2","dog","elephant"],
    ["3","cat","giraf"],
    ["4",np.nan,"ant"]],columns=["Day","Cat1","Cat2"])

In: df["Cat1"].combine_first(df["Cat2"])
Out: 
0    cat
1    dog
2    cat
3    ant
Name: Cat1, dtype: object

เปรียบเทียบกับคำตอบอื่น ๆ :

%timeit df["Cat1"].combine_first(df["Cat2"])
181 µs ± 11.3 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

%timeit df['Cat1'].fillna(df['Cat2'])
253 µs ± 10.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit np.where(df.Cat1.isnull(), df.Cat2, df.Cat1)
88.1 µs ± 793 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

ฉันไม่ได้ใช้วิธีนี้ด้านล่าง:

def is_missing(Cat1,Cat2):    
    if np.isnan(Cat1):        
        return Cat2
    else:
        return Cat1

df['Cat1'] = df.apply(lambda x: is_missing(x['Cat1'],x['Cat2']),axis=1)

เพราะจะเพิ่มข้อยกเว้น:

TypeError: ("ufunc 'isnan' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''", 'occurred at index 0')

ซึ่งหมายความว่า np.isnan สามารถนำไปใช้กับอาร์เรย์ NumPy ของ dtype ดั้งเดิม (เช่น np.float64) แต่จะเพิ่ม TypeError เมื่อใช้กับอาร์เรย์อ็อบเจ็กต์

ดังนั้นฉันจึงแก้ไขวิธีการ:

def is_missing(Cat1,Cat2):    
    if pd.isnull(Cat1):        
        return Cat2
    else:
        return Cat1

%timeit df.apply(lambda x: is_missing(x['Cat1'],x['Cat2']),axis=1)
701 µs ± 7.38 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

0

นี่เป็นวิธีการทั่วไปมากขึ้น (วิธีการเติมน่าจะดีกว่า)

def is_missing(Cat1,Cat2):    
    if np.isnan(Cat1):        
        return Cat2
    else:
        return Cat1

df['Cat1'] = df.apply(lambda x: is_missing(x['Cat1'],x['Cat2']),axis=1)

0

ฉันรู้ว่านี่เป็นคำถามเก่า แต่เมื่อเร็ว ๆ นี้ฉันมีความต้องการที่จะทำสิ่งที่คล้ายกัน ฉันสามารถใช้สิ่งต่อไปนี้:

df = pd.DataFrame([["1","cat","mouse"],
    ["2","dog","elephant"],
    ["3","cat","giraf"],
    ["4",np.nan,"ant"]],columns=["Day","Cat1","Cat2"])

print(df)

  Day Cat1      Cat2
0   1  cat     mouse
1   2  dog  elephant
2   3  cat     giraf
3   4  NaN       ant

df1 = df.bfill(axis=1).iloc[:, 1]
df1 = df1.to_frame()
print(df1)

ซึ่งให้ผลตอบแทน:

  Cat1
0  cat
1  dog
2  cat
3  ant

หวังว่านี่จะเป็นประโยชน์กับใครบางคน!

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