簡體   English   中英

(pandas)根據groupby和column條件填充NaN

[英](pandas) Fill NaN based on groupby and column condition

在groupby元素上使用'bfill'或'ffill'是微不足道的,但是如果你需要根據第三列中的條件在第二列中用特定值填充na呢?

例如:

>>> df=pd.DataFrame({'date':['01/10/2017', '02/09/2017', '02/10/2016','01/10/2017', '01/11/2017', '02/10/2016'], 'a':[1,1,1,2,2,2], 'b':[4,np.nan,6, 5, np.nan, 7]})
>>> df
   a    b        date
0  1  4.0  01/10/2017
1  1  NaN  02/09/2017
2  1  6.0  02/10/2016
3  2  5.0  01/10/2017
4  2  NaN  01/11/2017
5  2  7.0  02/10/2016

我需要按列'a'進行分組,並使用列'b'值填充NaN,其中該行的日期最接近NaN行中的日期。

所以輸出應該如下:

   a    b        date
0  1  4.0  01/10/2017
1  1  6.0  02/09/2017
2  1  6.0  02/10/2016
3  2  5.0  01/10/2017
4  2  5.0  01/11/2017
5  2  7.0  02/10/2016

假設有一個nearest_date()函數,它接受NaN日期和該組中其他日期的列表,並返回最接近的日期。

我正在嘗試找到一個不必遍歷行的干凈解決方案,理想情況下可以使用帶lambda的apply()。 有任何想法嗎?

這應該工作:

df['closest_date_by_a'] = df.groupby('a')['date'].apply(closest_date)
df['b'] = df.groupby(['a', 'closest_date_by_a'])['b'].ffill().bfill()

給定一個函數( closest_date() ),您需要按組應用該函數,以便計算每個組中行的最接近日期。 然后,您可以按主分組列( a )和最近的日期列( closest_date_by_a )進行closest_date_by_a然后執行填充。

確保您的date列實際上是日期。

df = pd.DataFrame(
    {'date': ['01/10/2017', '02/09/2017', '02/10/2016','01/10/2017', '01/11/2017', '02/10/2016'],
     'a':[1,1,1,2,2,2], 'b':[4,np.nan,6, 5, np.nan, 7]})
df.date = pd.to_datetime(df.date)

print(df)

   a    b       date
0  1  4.0 2017-01-10
1  1  NaN 2017-02-09
2  1  6.0 2016-02-10
3  2  5.0 2017-01-10
4  2  NaN 2017-01-11
5  2  7.0 2016-02-10

使用dropna()后使用method='nearest' reindex

def fill_with_nearest(df):
    s = df.set_index('date').b
    s = s.dropna().reindex(s.index, method='nearest')
    s.index = df.index
    return s

df.loc[df.b.isnull(), 'b'] = df.groupby('a').apply(fill_with_nearest).reset_index(0, drop=True)

print(df)

   a    b       date
0  1  4.0 2017-01-10
1  1  4.0 2017-02-09
2  1  6.0 2016-02-10
3  2  5.0 2017-01-10
4  2  5.0 2017-01-11
5  2  7.0 2016-02-10

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM