[英]Fill NaN values wit mean of previous rows?
我必須用前 3 個實例的平均值填充 dataframe 中列的 nan 值。 這是以下示例:
df = pd.DataFrame({'col1': [1, 3, 4, 5, np.NaN, np.NaN, np.NaN, 7]})
df
col1
0 1.0
1 3.0
2 4.0
3 5.0
4 NaN
5 NaN
6 NaN
7 7.0
這是我需要的 output:
col1
0 1.0
1 3.0
2 4.0
3 5.0
4 4.0
5 4.3
6 4.4
7 7.0
我嘗試了 pd.rolling,但是當列在滾動中具有多個 NaN 值時,它不會按我想要的方式工作:
df.fillna(df.rolling(3, min_periods=1).mean().shift())
col1
0 1.0
1 3.0
2 4.0
3 5.0
4 4.0 # np.nanmean([3, 4, 5])
5 4.5 # np.nanmean([np.NaN, 4, 5])
6 5.0 # np.nanmean([np.NaN, np.naN ,5])
7 7.0
有人可以幫我嗎? 提前致謝!
可能不是最有效但簡潔並完成工作
from functools import reduce
reduce(lambda d, _: d.fillna(d.rolling(3, min_periods=3).mean().shift()), range(df['col1'].isna().sum()), df)
output
col1
0 1.000000
1 3.000000
2 4.000000
3 5.000000
4 4.000000
5 4.333333
6 4.444444
7 7.000000
我們基本上使用fillna
但要求min_periods=3
意味着它一次只會填充一個 NaN,或者更確切地說是那些在其前面有三個非 NaN 數字的 NaN。 然后我們使用reduce
重復這個操作的次數與col1
中的NaNs一樣多
我嘗試了兩種方法來解決這個問題。 一個是在 dataframe 上的循環,第二個本質上是多次嘗試您建議的方法,以收斂到正確的答案。
對於 dataframe 中的每一行,從 col1 中獲取值。 然后,取最后一行的平均值。 (如果我們在 dataframe 的開頭,此列表中可能少於 3 個。)如果值為 NaN,則將其替換為平均值。 然后,將該值保存回 dataframe。 如果最后一行的值列表中的值超過 3 個,則刪除最后一個。
def impute(df2, col_name):
last_3 = []
for index in df.index:
val = df2.loc[index, col_name]
if len(last_3) > 0:
imputed = np.nanmean(last_3)
else:
imputed = None
if np.isnan(val):
val = imputed
last_3.append(val)
df2.loc[index, col_name] = val
if len(last_3) > 3:
last_3.pop(0)
這里的核心思想是注意在您的 pd.rolling 示例中,第一個 NA 替換值是正確的。 因此,您應用滾動平均值,為每次運行的 NA 值取第一個 NA 值,然后使用該數字。 如果你重復應用這個,你填寫第一個缺失值,然后是第二個缺失值,然后是第三個。 您需要運行此循環的次數與最長的連續 NA 值系列一樣多。
def impute(df2, col_name):
while df2[col_name].isna().any().any():
# If there are multiple NA values in a row, identify just
# the first one
first_na = df2[col_name].isna().diff() & df2[col_name].isna()
# Compute mean of previous 3 values
imputed = df2.rolling(3, min_periods=1).mean().shift()[col_name]
# Replace NA values with mean if they are very first NA
# value in run of NA values
df2.loc[first_na, col_name] = imputed
在 80000 行 dataframe 上運行這兩個,我得到以下結果:
Loop approach takes 20.744 seconds
Repeated column operation takes 0.056 seconds
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.