用中位数替换 NaN 值?
Replace NaN value with a median?
所以我尝试使用 Pandas 将 table 中的所有 NaN 值替换为特定范围内的中值。我正在处理更大的数据集,但例如
np.random.seed(0)
rng = pd.date_range('2020-09-24', periods=20, freq='0.2H')
df = pd.DataFrame({ 'Date': rng, 'Val': np.random.randn(len(rng)), 'Dist' :np.random.randn(len(rng)) })
df.Dist[df.Dist<=-0.6] = np.nan
df.Val[df.Val<=-0.5] = np.nan
我想要做的是用该列每小时的中值替换 Val 和 Dist 的 NaN 值。我已经设法在单独的参考 table:
中获得中值
df.set_index('Date', inplace=True)
df = df.assign(Hour = lambda x : x.index.hour)
df_val = df[["Val", "Hour"]].groupby("Hour").median()
df_dist = df[["Dist", "Hour"]].groupby("Hour").median()
但现在我已经尝试了以下所有各种形式的命令,但无法弄清楚如何填充 NaN 值。
df[["Val","Hour"]].mask(df['Val'].isna(), df_val.iloc[df.Hour], inplace=True)
df.where(df['Val'].notna(), other=df_val[df.Hour],axis = 0)
df["Val"] = np.where(df['Val'].notna(), df['Val'], df_val(df.Hour))
df.replace({"Val":{np.nan:df_val[df.Hour]}, "Dist":{np.nan:df_dist[df.Hour]}})
您可以使用 groupby.transform
和 fillna:
cols = ['Val','Dist']
df[cols] = df[cols].fillna(df.groupby(df.Date.dt.floor('H'))
[cols].transform('median')
)
输出:
Date Val Dist
0 2020-09-24 00:00:00 1.764052 0.864436
1 2020-09-24 00:12:00 0.400157 0.653619
2 2020-09-24 00:24:00 0.978738 0.864436
3 2020-09-24 00:36:00 2.240893 0.864436
4 2020-09-24 00:48:00 1.867558 2.269755
5 2020-09-24 01:00:00 0.153690 0.757559
6 2020-09-24 01:12:00 0.950088 0.045759
7 2020-09-24 01:24:00 -0.151357 -0.187184
8 2020-09-24 01:36:00 -0.103219 1.532779
9 2020-09-24 01:48:00 0.410599 1.469359
10 2020-09-24 02:00:00 0.144044 0.154947
11 2020-09-24 02:12:00 1.454274 0.378163
12 2020-09-24 02:24:00 0.761038 0.154947
13 2020-09-24 02:36:00 0.121675 0.154947
14 2020-09-24 02:48:00 0.443863 -0.347912
15 2020-09-24 03:00:00 0.333674 0.156349
16 2020-09-24 03:12:00 1.494079 1.230291
17 2020-09-24 03:24:00 -0.205158 1.202380
18 2020-09-24 03:36:00 0.313068 -0.387327
19 2020-09-24 03:48:00 0.323371 -0.302303
您可以使用 groupby -> transform
操作,同时还利用 pd.Grouper
class 执行每小时转换。这实际上将创建一个与原始数据框形状相同的数据框,其中包含每小时的中位数。一旦有了这个,就可以直接使用 DataFrame.fillna
hourly_medians = df.groupby(pd.Grouper(key="Date", freq="H")).transform("median")
out = df.fillna(hourly_medians)
print(out)
Date Val Dist
0 2020-09-24 00:00:00 1.764052 0.864436
1 2020-09-24 00:12:00 0.400157 0.653619
2 2020-09-24 00:24:00 0.978738 0.864436
3 2020-09-24 00:36:00 2.240893 0.864436
4 2020-09-24 00:48:00 1.867558 2.269755
5 2020-09-24 01:00:00 0.153690 0.757559
6 2020-09-24 01:12:00 0.950088 0.045759
7 2020-09-24 01:24:00 -0.151357 -0.187184
8 2020-09-24 01:36:00 -0.103219 1.532779
9 2020-09-24 01:48:00 0.410599 1.469359
10 2020-09-24 02:00:00 0.144044 0.154947
11 2020-09-24 02:12:00 1.454274 0.378163
12 2020-09-24 02:24:00 0.761038 0.154947
13 2020-09-24 02:36:00 0.121675 0.154947
14 2020-09-24 02:48:00 0.443863 -0.347912
15 2020-09-24 03:00:00 0.333674 0.156349
16 2020-09-24 03:12:00 1.494079 1.230291
17 2020-09-24 03:24:00 -0.205158 1.202380
18 2020-09-24 03:36:00 0.313068 -0.387327
19 2020-09-24 03:48:00 0.323371 -0.302303
使用你所做的,我会这样做:
df.Val = df.Val.fillna(df.Hour.map(df_val.squeeze()))
df.Dist = df.Val.fillna(df.Hour.map(df_dist.squeeze()))
您可以为所需的任务定义一个函数:
def impute_nan(df,var,median):
df['new_'+var] = df[var].fillna(median)
median = df.Val.medain()
median
impute_nan(df,'Val',median)
这将为您提供一个名为 'new_Val' 的新列,其中替换了 NAN 值。
所以我尝试使用 Pandas 将 table 中的所有 NaN 值替换为特定范围内的中值。我正在处理更大的数据集,但例如
np.random.seed(0)
rng = pd.date_range('2020-09-24', periods=20, freq='0.2H')
df = pd.DataFrame({ 'Date': rng, 'Val': np.random.randn(len(rng)), 'Dist' :np.random.randn(len(rng)) })
df.Dist[df.Dist<=-0.6] = np.nan
df.Val[df.Val<=-0.5] = np.nan
我想要做的是用该列每小时的中值替换 Val 和 Dist 的 NaN 值。我已经设法在单独的参考 table:
中获得中值df.set_index('Date', inplace=True)
df = df.assign(Hour = lambda x : x.index.hour)
df_val = df[["Val", "Hour"]].groupby("Hour").median()
df_dist = df[["Dist", "Hour"]].groupby("Hour").median()
但现在我已经尝试了以下所有各种形式的命令,但无法弄清楚如何填充 NaN 值。
df[["Val","Hour"]].mask(df['Val'].isna(), df_val.iloc[df.Hour], inplace=True)
df.where(df['Val'].notna(), other=df_val[df.Hour],axis = 0)
df["Val"] = np.where(df['Val'].notna(), df['Val'], df_val(df.Hour))
df.replace({"Val":{np.nan:df_val[df.Hour]}, "Dist":{np.nan:df_dist[df.Hour]}})
您可以使用 groupby.transform
和 fillna:
cols = ['Val','Dist']
df[cols] = df[cols].fillna(df.groupby(df.Date.dt.floor('H'))
[cols].transform('median')
)
输出:
Date Val Dist
0 2020-09-24 00:00:00 1.764052 0.864436
1 2020-09-24 00:12:00 0.400157 0.653619
2 2020-09-24 00:24:00 0.978738 0.864436
3 2020-09-24 00:36:00 2.240893 0.864436
4 2020-09-24 00:48:00 1.867558 2.269755
5 2020-09-24 01:00:00 0.153690 0.757559
6 2020-09-24 01:12:00 0.950088 0.045759
7 2020-09-24 01:24:00 -0.151357 -0.187184
8 2020-09-24 01:36:00 -0.103219 1.532779
9 2020-09-24 01:48:00 0.410599 1.469359
10 2020-09-24 02:00:00 0.144044 0.154947
11 2020-09-24 02:12:00 1.454274 0.378163
12 2020-09-24 02:24:00 0.761038 0.154947
13 2020-09-24 02:36:00 0.121675 0.154947
14 2020-09-24 02:48:00 0.443863 -0.347912
15 2020-09-24 03:00:00 0.333674 0.156349
16 2020-09-24 03:12:00 1.494079 1.230291
17 2020-09-24 03:24:00 -0.205158 1.202380
18 2020-09-24 03:36:00 0.313068 -0.387327
19 2020-09-24 03:48:00 0.323371 -0.302303
您可以使用 groupby -> transform
操作,同时还利用 pd.Grouper
class 执行每小时转换。这实际上将创建一个与原始数据框形状相同的数据框,其中包含每小时的中位数。一旦有了这个,就可以直接使用 DataFrame.fillna
hourly_medians = df.groupby(pd.Grouper(key="Date", freq="H")).transform("median")
out = df.fillna(hourly_medians)
print(out)
Date Val Dist
0 2020-09-24 00:00:00 1.764052 0.864436
1 2020-09-24 00:12:00 0.400157 0.653619
2 2020-09-24 00:24:00 0.978738 0.864436
3 2020-09-24 00:36:00 2.240893 0.864436
4 2020-09-24 00:48:00 1.867558 2.269755
5 2020-09-24 01:00:00 0.153690 0.757559
6 2020-09-24 01:12:00 0.950088 0.045759
7 2020-09-24 01:24:00 -0.151357 -0.187184
8 2020-09-24 01:36:00 -0.103219 1.532779
9 2020-09-24 01:48:00 0.410599 1.469359
10 2020-09-24 02:00:00 0.144044 0.154947
11 2020-09-24 02:12:00 1.454274 0.378163
12 2020-09-24 02:24:00 0.761038 0.154947
13 2020-09-24 02:36:00 0.121675 0.154947
14 2020-09-24 02:48:00 0.443863 -0.347912
15 2020-09-24 03:00:00 0.333674 0.156349
16 2020-09-24 03:12:00 1.494079 1.230291
17 2020-09-24 03:24:00 -0.205158 1.202380
18 2020-09-24 03:36:00 0.313068 -0.387327
19 2020-09-24 03:48:00 0.323371 -0.302303
使用你所做的,我会这样做:
df.Val = df.Val.fillna(df.Hour.map(df_val.squeeze()))
df.Dist = df.Val.fillna(df.Hour.map(df_dist.squeeze()))
您可以为所需的任务定义一个函数:
def impute_nan(df,var,median):
df['new_'+var] = df[var].fillna(median)
median = df.Val.medain()
median
impute_nan(df,'Val',median)
这将为您提供一个名为 'new_Val' 的新列,其中替换了 NAN 值。