Source code for impute
import numpy as np
import pandas as pd
from sklearn.preprocessing import StandardScaler
from tqdm import tqdm
from pkg import neighbor as nbr
[docs]def impute_by_time_mean(df: pd.DataFrame) -> pd.DataFrame:
"""
時間平均による欠損値補完を行なう。
Parameters
----------
df : pandas.DataFrame of shape (n_objects, n_mjds)
欠損値補完を行なう m_ap30 の表。
Returns
-------
df : pandas.DataFrame of shape (n_objects, n_mjds)
時間平均により欠損値補完を行なった m_ap30 の表。
"""
df_mean = df.mean(axis=1)
df = df.T
df.fillna(df_mean, inplace=True)
df = df.T
return df
[docs]def get_moving_average_num(
df: pd.DataFrame, width_moving_average: float) -> np.ndarray:
"""
時間幅 width_moving_average の移動平均による欠損値補完を行なう際に、
指定された pandas.DataFrame のそれぞれの mjd の列に対して、
直前の何個の要素の平均を取ればよいのかを格納した numpy.ndarray を返す。
Parameters
----------
df : pandas.DataFrame of shape (n_objects, n_mjds)
欠損値補完を行いたい m_ap30 の表。
width_moving_average : float
移動平均の時間幅。単位は mjd。
Returns
-------
ma_num : numpy.ndarray
時間幅 width_moving_average の移動平均による欠損値補完を行なう際に、
指定された pandas.DataFrame のそれぞれの mjd の列に対して、
直前の何個の要素の平均を取ればよいのかのリスト。
"""
mjd_list = df.columns.values
mjd_diff = mjd_list[1:] - mjd_list[:-1]
ma_num = np.empty_like(mjd_diff, dtype=np.int)
for i in range(len(ma_num)):
cnt = 0
w_tmp = mjd_diff[i]
while w_tmp <= width_moving_average:
cnt += 1
if i < cnt:
break
w_tmp += mjd_diff[i - cnt]
ma_num[i] = cnt
return ma_num
[docs]def impute_by_moving_average(
df: pd.DataFrame, width_moving_average: float) -> None:
"""
移動平均による欠損値補完を行なう。
Parameters
----------
df : pandas.DataFrame of shape (n_objects, n_mjds)
欠損値補完を行なう m_ap30 の表。
width_moving_average : float
移動平均の時間幅。単位は mjd。
"""
ma_num = get_moving_average_num(df,
width_moving_average=width_moving_average)
# 先頭の mjd を除く mjd の NaN を、その object の直前の ma_num 個の平均値で補完
for col in range(len(df.columns) - 1, 0, -1):
if ma_num[col - 1] > 0:
df.iloc[:, col].fillna(df.iloc[:, col \
- ma_num[col - 1]:col].mean(axis=1).round(4),
inplace=True)
[docs]def get_spatial_mean(df: pd.DataFrame) -> pd.DataFrame:
"""
object ごとに標準化した計測値の、mjd ごとのすべての object に対する平均値を、
それぞれの object の元の表現にスケールバックしたものを返す。
Parameters
----------
df : pandas.DataFrame of shape (n_objects, n_mjds)
m_ap30 の表。
Returns
-------
df_std_mean_inv : pandas.DataFrame of shape (n_objects, n_mjds)
object ごとに標準化した計測値の、mjd ごとのすべての object に対する平均値を、
それぞれの object の元の表現にスケールバックしたもの。
"""
scaler = StandardScaler()
df_std = pd.DataFrame(scaler.fit_transform(df.T).T,
index=df.index, columns=df.columns)
s_std_mean = df_std.mean(axis=0)
df_std_mean \
= pd.DataFrame(np.array([s_std_mean.values for _ in range(len(df))]),
index=df.index, columns=df.columns)
df_std_mean_inv = pd.DataFrame(scaler.inverse_transform(df_std_mean.T).T,
index=df.index, columns=df.columns).round(4)
return df_std_mean_inv
[docs]def impute_by_spatial_mean(df: pd.DataFrame) -> None:
"""
空間平均による欠損値補完を行なう。
Parameters
----------
df : pandas.DataFrame of shape (n_objects, n_mjds)
欠損値補完を行なう m_ap30 の表。これが補完される。
"""
df_std_mean_inv = get_spatial_mean(df)
df.fillna(df_std_mean_inv, inplace=True)
[docs]def impute_by_nbr(df: pd.DataFrame, df_coord: pd.DataFrame) -> None:
"""
空間的に近傍に存在する object の、object ごとに標準化した計測値の平均値を、
それぞれの object の元の表現にスケールバックした値による欠損値補完を行なう。
Parameters
----------
df : pandas.DataFrame of shape (n_objects, n_mjds)
欠損値補完を行なう m_ap30 の表。これが補完される。
df_coord : pandas.DataFrame of shape (n_objects, n_features)
columns に `coord_ra` と `coord_dec` をもつ表。
df_coord.columns[1] が `coord_ra` で、
df_coord.columns[2] が `coord_dec`。
"""
# object ごとに計測値を標準化
scaler = StandardScaler()
df_std = pd.DataFrame(scaler.fit_transform(df.T).T,
index=df.index, columns=df.columns)
# それぞれの object の空間的に近傍の object の標準化された計測値の平均を、
# mjd ごとに算出
neighbor_idx = nbr.get_neighbor_idx(df, df_coord)
df_std_mean_nbr = pd.DataFrame(index=df.index, columns=df.columns)
print('\nimpute_by_nbr\n')
for i in tqdm(range(len(df_std_mean_nbr))):
df_std_mean_nbr.iloc[i] = df_std.loc[neighbor_idx[i]].mean(axis=0)
# 得られた値を、それぞれの object の元の表現にスケールバックする
scaler = StandardScaler()
scaler.fit(df.T)
df_std_mean_nbr_inv \
= pd.DataFrame(scaler.inverse_transform(df_std_mean_nbr.T).T,
index=df_std_mean_nbr.index,
columns=df_std_mean_nbr.columns).round(4)
# これを補完する
df.fillna(df_std_mean_nbr_inv, inplace=True)
[docs]def impute_by_nbr_and_spatial_mean(
df: pd.DataFrame, df_coord: pd.DataFrame) -> None:
"""
まず空間的近傍平均により欠損値補完を行ない、
補完されなかった部分を空間平均により補完する。
Parameters
----------
df : pandas.DataFrame of shape (n_objects, n_mjds)
欠損値補完を行なう m_ap30 の表。これが補完される。
df_coord : pandas.DataFrame of shape (n_objects, n_features)
columns に `coord_ra` と `coord_dec` をもつ表。
df_coord.columns[1] が `coord_ra` で、
df_coord.columns[2] が `coord_dec`。
"""
df_std_mean_inv = get_spatial_mean(df)
impute_by_nbr(df, df_coord)
df.fillna(df_std_mean_inv, inplace=True)