นุ่น: คำนวณค่าที่หายไปตามจำนวนที่กำหนดก่อน/หลังชุดค่าที่มีอยู่

สมมติว่าฉันมีอนุกรมเวลาซึ่งโดยปกติแล้วฉันมีข้อมูลสำหรับช่วงหลายปีที่ต่อเนื่องกัน แต่ไม่มีค่าก่อนและหลังช่วงนั้น เช่นนี้

df = pd.DataFrame({'year': ["2000","2001","2002", "2003","2004", "2005","2006", "2007"], 'cakes eaten': [np.nan, np.nan, np.nan, 3, 4, 5, np.nan, np.nan]})
print(df)

   year  cakes eaten
0  2000          NaN
1  2001          NaN
2  2002          NaN
3  2003          3.0
4  2004          4.0
5  2005          5.0
6  2006          NaN
7  2007          NaN

มีวิธีเติมค่าที่หายไป (ตามจำนวนที่กำหนด) ตามแนวโน้มที่เห็นในค่าที่มีอยู่หรือไม่?

สมมติว่าฉันต้องการเติมค่าสูงสุด 2 ค่าในแต่ละทิศทาง ผลลัพธ์ที่ได้จะมีลักษณะดังนี้:

   year  cakes eaten
0  2000          NaN
1  2001          1.0
2  2002          2.0
3  2003          3.0
4  2004          4.0
5  2005          5.0
6  2006          6.0
7  2007          7.0

นอกจากนี้: มีวิธีที่จะทำให้แน่ใจว่าการใส่ค่านี้จะดำเนินการเมื่อมีค่าที่มีอยู่เพียงพอเท่านั้น เช่น ฉันต้องการเติมค่าสูงสุด 2 ค่าในแต่ละทิศทางหากมีอย่างน้อย 3 ค่า ค่าที่มีอยู่ (หรือในแง่ทั่วไป ให้กรอก n เฉพาะในกรณีที่ n + m เป็นค่าว่าง) ?


person Christian O.    schedule 29.12.2020    source แหล่งที่มา
comment
คุณจะระบุแนวโน้มที่เห็นในค่าที่มีอยู่ได้อย่างไร   -  person Dani Mesejo    schedule 29.12.2020


คำตอบ (2)


ฉันจะใช้ interpolate() ที่กล่าวถึง มีหลายวิธีที่คุณสามารถใช้ได้ซึ่งจะให้ผลลัพธ์ที่แตกต่างกัน ฉันใช้วิธี krogh เพื่อรับเส้นแนวโน้มเชิงเส้น limit_direction='both' จำเป็นต้องเติมแนวโน้มทั้งสองทิศทาง:

test_dict  = {'col': [np.nan, np.nan,np.nan, np.nan, np.nan, 4, 5, 6 ,np.nan]}
df = pd.DataFrame(test_dict)
df['trend'] = df['col'].interpolate(method='krogh', limit_direction='both')

    col trend
0   NaN -1.0
1   NaN 0.0
2   NaN 1.0
3   NaN 2.0
4   NaN 3.0
5   4.0 4.0
6   5.0 5.0
7   6.0 6.0
8   NaN 7.0

เมื่อเสร็จแล้ว คุณสามารถลบค่าแนวโน้ม below 0 ที่ไม่จำเป็นออกได้

person olv1do    schedule 29.12.2020
comment
ขอขอบคุณที่ชี้ให้ฉันไปที่ฟังก์ชันการแก้ไขอีกครั้ง ดูเหมือนว่าจะสามารถทำสิ่งที่ฉันต้องการได้จริงๆ Krogh ทำงานได้ดีมากสำหรับตัวอย่างที่ฉันโพสต์ด้านบน แต่สร้างค่าที่แปลกมากหากแนวโน้มไม่เป็นเส้นตรงอย่างสมบูรณ์ อย่างไรก็ตาม ฉันพบว่าวิธี spline กับ order = 2 ทำงานได้ดีกว่ามาก - person Christian O.; 29.12.2020

ขอบคุณ @ olv1do ที่แสดงให้ฉันเห็นว่า interpolate( ) ทำสิ่งที่ฉันต้องการ

การใช้การประมาณค่าและ .first_valid_index และ .last_valid_index ช่วยให้สามารถใช้พฤติกรรมที่ต้องการได้:

#impute n values in both directions if at least m values are available
def interpolate(data, n, m):
  first_valid = data['cakes eaten'].first_valid_index()
  last_valid = data['cakes eaten'].last_valid_index()

  if(abs(first_valid - last_valid) + 1 >= m):
    data['imputed'] = data['cakes eaten'].interpolate(method='spline',order = 1, limit_direction='both', limit = n)
  return data

สำหรับตัวอย่างจากคำถาม:

df = pd.DataFrame({'year': ["2000","2001","2002", "2003","2004", "2005","2006", "2007"], 'cakes eaten': [np.nan, np.nan, np.nan, 3, 4, 5, np.nan, np.nan]})
interpolate(df, 2,3)

year    cakes eaten     imputed
0   2000    NaN     NaN
1   2001    NaN     1.0
2   2002    NaN     2.0
3   2003    3.0     3.0
4   2004    4.0     4.0
5   2005    5.0     5.0
6   2006    NaN     6.0
7   2007    NaN     7.0

ไม่ทำอะไรเลยหากมีค่าน้อยกว่า m:

df = pd.DataFrame({'year': ["2000","2001","2002", "2003","2004", "2005","2006", "2007"], 'cakes eaten': [np.nan, np.nan, np.nan, 3, 4,  np.nan, np.nan, np.nan]})
interpolate(df, 2,3)

    year    cakes eaten
0   2000    NaN
1   2001    NaN
2   2002    NaN
3   2003    3.0
4   2004    4.0
5   2005    NaN
6   2006    NaN
7   2007    NaN

นอกจากนี้ เมธอด spline ยังทำงานได้ดีมากหากค่าไม่เป็นเส้นตรงอย่างสมบูรณ์ดังตัวอย่างของฉัน:

df = pd.DataFrame({'year': ["2000","2001","2002", "2003","2004", "2005","2006", "2007"], 'cakes eaten': [np.nan, np.nan, 1, 4, 2,  3, np.nan, np.nan]})
interpolate(df, 1,4)

    year    cakes eaten     imputed
0   2000    NaN     NaN
1   2001    NaN     1.381040
2   2002    1.0     1.000000
3   2003    4.0     4.000000
4   2004    2.0     2.000000
5   2005    3.0     3.000000
6   2006    NaN     3.433167
7   2007    NaN     NaN
person Christian O.    schedule 29.12.2020