จะแทนที่ NaN ด้วยค่านำหน้าใน DataFrame ของแพนด้าได้อย่างไร


158

สมมติว่าฉันมี DataFrame กับNaNs:

>>> import pandas as pd
>>> df = pd.DataFrame([[1, 2, 3], [4, None, None], [None, None, 9]])
>>> df
    0   1   2
0   1   2   3
1   4 NaN NaN
2 NaN NaN   9

สิ่งที่ฉันต้องทำคือแทนที่ทุกค่าด้วยค่าที่NaNไม่ใช่NaNค่าแรกในคอลัมน์เดียวกันด้านบน สันนิษฐานว่าแถวแรกจะไม่มีNaN. ดังนั้นสำหรับตัวอย่างก่อนหน้าผลลัพธ์จะเป็น

   0  1  2
0  1  2  3
1  4  2  3
2  4  2  9

ฉันสามารถวนรอบ DataFrame ทั้งคอลัมน์ต่อคอลัมน์องค์ประกอบโดยองค์ประกอบและตั้งค่าโดยตรง แต่มีวิธีง่ายๆ (โดยไม่ต้องวนซ้ำ) ในการบรรลุสิ่งนี้หรือไม่

คำตอบ:


237

คุณสามารถใช้fillnaวิธีการบน DataFrame และระบุวิธีการเป็นffill(ไปข้างหน้าเติม):

>>> df = pd.DataFrame([[1, 2, 3], [4, None, None], [None, None, 9]])
>>> df.fillna(method='ffill')
   0  1  2
0  1  2  3
1  4  2  3
2  4  2  9

วิธีนี้ ...

เผยแพร่การสังเกตที่ถูกต้องล่าสุดส่งต่อไปยังครั้งต่อไปที่ถูกต้อง

ในทางตรงกันข้ามยังมีbfillวิธีการ

วิธีนี้ไม่ได้แก้ไข DataFrame แบบแทนที่คุณจะต้องเชื่อมโยง DataFrame ที่ส่งคืนกลับเข้ากับตัวแปรหรือระบุinplace=True:

df.fillna(method='ffill', inplace=True)

จะเกิดอะไรขึ้นถ้าเซลล์ว่างอยู่ในดัชนีชื่อคอลัมน์ (กล่าวคือสองคอลัมน์ไม่มีชื่อ แต่มีข้อมูลมีวิธีใช้ bfill หรือ ffill เพื่อเติมเซลล์ดัชนีคอลัมน์ว่างด้วยเซลล์ใน แถวด้านล่างทันทีหรือไม่ตัวอย่างเช่น: df = pd.DataFrame ({'col1': [2, 4, 8], 'col2': [2, 0, 0], '': [10, 2, 1]} , index = ['falcon', 'dog', 'spider' ']) ฉันจะใช้ bfill หรือ ffill เพื่อเปลี่ยนชื่อของคอลัมน์ที่สามเป็น 10 ได้อย่างไร (ซึ่งเป็นค่าของแถวที่อยู่ด้านล่างชื่อคอลัมน์ที่สามที่ว่างเปล่า ขอบคุณ!
GbG

33

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

>>> example = pd.DataFrame({'number':[0,1,2,nan,4,nan,6,7,8,9],'name':list('aaabbbcccc')})
>>> example
  name  number
0    a     0.0
1    a     1.0
2    a     2.0
3    b     NaN
4    b     4.0
5    b     NaN
6    c     6.0
7    c     7.0
8    c     8.0
9    c     9.0
>>> example.groupby('name')['number'].fillna(method='ffill') # fill in row 5 but not row 3
0    0.0
1    1.0
2    2.0
3    NaN
4    4.0
5    4.0
6    6.0
7    7.0
8    8.0
9    9.0
Name: number, dtype: float64

สิ่งที่ฉันกำลังมองหา ty
Tony

18

คุณสามารถใช้pandas.DataFrame.fillnaกับmethod='ffill'ตัวเลือก 'ffill'ย่อมาจาก 'forward fill' และจะเผยแพร่การสังเกตที่ถูกต้องไปข้างหน้า อีกทางเลือกหนึ่งคือ'bfill'ทำงานในลักษณะเดียวกัน แต่ย้อนกลับ

import pandas as pd

df = pd.DataFrame([[1, 2, 3], [4, None, None], [None, None, 9]])
df = df.fillna(method='ffill')

print(df)
#   0  1  2
#0  1  2  3
#1  4  2  3
#2  4  2  9

นอกจากนี้ยังมีฟังก์ชันคำพ้องความหมายโดยตรงสำหรับสิ่งนี้pandas.DataFrame.ffillเพื่อให้ง่ายขึ้น


15

สิ่งหนึ่งที่ฉันสังเกตเห็นเมื่อลองวิธีนี้คือถ้าคุณมี N / A ที่จุดเริ่มต้นหรือจุดสิ้นสุดของอาร์เรย์ ffill และ bfill จะไม่ได้ผล คุณต้องการทั้งสองอย่าง

In [224]: df = pd.DataFrame([None, 1, 2, 3, None, 4, 5, 6, None])

In [225]: df.ffill()
Out[225]:
     0
0  NaN
1  1.0
...
7  6.0
8  6.0

In [226]: df.bfill()
Out[226]:
     0
0  1.0
1  1.0
...
7  6.0
8  NaN

In [227]: df.bfill().ffill()
Out[227]:
     0
0  1.0
1  1.0
...
7  6.0
8  6.0

ยอดเยี่ยม. ฉันต้องการสิ่งนี้สำหรับปัญหาของฉัน เติมทั้งก่อนและหลัง ขอบคุณมาก.
Prometheus

เยี่ยมมาก ฉันต้องการวิธีนี้ ขอบคุณ
Junkrat


5

เวอร์ชันคอลัมน์เดียวเท่านั้น

  • เติม NAN ด้วยค่าสุดท้ายที่ถูกต้อง
df[column_name].fillna(method='ffill', inplace=True)
  • กรอก NAN ด้วยค่าที่ถูกต้องถัดไป
df[column_name].fillna(method='backfill', inplace=True)

5

เพียงแค่เห็นด้วยกับffillวิธีการ แต่ข้อมูลเพิ่มเติมอย่างหนึ่งคือคุณสามารถ จำกัด การเติมไปข้างหน้าด้วยอาร์กิวเมนต์คำหลักlimitได้

>>> import pandas as pd    
>>> df = pd.DataFrame([[1, 2, 3], [None, None, 6], [None, None, 9]])

>>> df
     0    1   2
0  1.0  2.0   3
1  NaN  NaN   6
2  NaN  NaN   9

>>> df[1].fillna(method='ffill', inplace=True)
>>> df
     0    1    2
0  1.0  2.0    3
1  NaN  2.0    6
2  NaN  2.0    9

ขณะนี้มีlimitอาร์กิวเมนต์คำหลัก

>>> df[0].fillna(method='ffill', limit=1, inplace=True)

>>> df
     0    1  2
0  1.0  2.0  3
1  1.0  2.0  6
2  NaN  2.0  9

1

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

df = pd.DataFrame([["device1", 1, 'first val of device1'], ["device2", 2, 'first val of device2'], ["device3", 3, 'first val of device3']])
df.pivot(index=1, columns=0, values=2).fillna(method='ffill').unstack().reset_index(name='value')

ผลลัพธ์:

        0   1   value
0   device1     1   first val of device1
1   device1     2   first val of device1
2   device1     3   first val of device1
3   device2     1   None
4   device2     2   first val of device2
5   device2     3   first val of device2
6   device3     1   None
7   device3     2   None
8   device3     3   first val of device3

0

คุณสามารถใช้fillnaเพื่อลบหรือแทนที่ค่า NaN

NaN ลบ

import pandas as pd

df = pd.DataFrame([[1, 2, 3], [4, None, None], [None, None, 9]])

df.fillna(method='ffill')
     0    1    2
0  1.0  2.0  3.0
1  4.0  2.0  3.0
2  4.0  2.0  9.0

NaN แทนที่

df.fillna(0) # 0 means What Value you want to replace 
     0    1    2
0  1.0  2.0  3.0
1  4.0  0.0  0.0
2  0.0  0.0  9.0

อ้างอิงpandas.DataFrame.fillna

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