# Path: impyute/ops/matrix.py
# def nan_indices(data):
# def map_nd(fn, arr):
# def every_nd(fn, arr):
# 
# Path: impyute/ops/wrapper.py
# @wraps(fn)
# def wrapper(*args, **kwargs):
#     postprocess_fn = None
#     ## convert tuple to list so args can be modified
#     args = list(args)
#     ## Either make a copy or use a pointer to the original
#     if kwargs.get('inplace'):
#         args[0] = args[0]
#     else:
#         args[0] = args[0].copy()
# 
#     ## If input data is a dataframe then cast the input to an np.array
#     ## and set an indicator flag before continuing
#     pd_DataFrame = get_pandas_df()
#     if pd_DataFrame and isinstance(args[0], pd_DataFrame):
#         postprocess_fn = pd_DataFrame
#         args[0] = args[0].values
# 
#     ## function invokation
#     results = u.execute_fn_with_args_and_or_kwargs(fn, args, kwargs)
# 
#     ## cast the output back to a DataFrame.
#     if postprocess_fn is not None:
#         results = postprocess_fn(results)
# 
#     return results
# 
# Path: impyute/ops/inverse_distance_weighting.py
# def shepards(distances, power=2):
# def to_percentage(vec):
# 
# Path: impyute/imputation/cs/central_tendency.py
# @wrapper.wrappers
# @wrapper.checks
# def mean(data):
#     """ Substitute missing values with the mean of that column.
# 
#     Parameters
#     ----------
#     data: numpy.ndarray
#         Data to impute.
# 
#     Returns
#     -------
#     numpy.ndarray
#         Imputed data.
# 
#     """
#     nan_xy = matrix.nan_indices(data)
#     for x_i, y_i in nan_xy:
#         row_wo_nan = data[:, [y_i]][~np.isnan(data[:, [y_i]])]
#         new_value = np.mean(row_wo_nan)
#         data[x_i][y_i] = new_value
#     return data


import numpy as np
from scipy.spatial import KDTree
from impyute.ops import matrix
from impyute.ops import wrapper
from impyute.ops import inverse_distance_weighting as idw
from . import mean
        >>> data[0][2] =  np.nan
        >>> data
        array([[ 0.,  1., nan,  3.,  4.],
               [ 5.,  6.,  7.,  8.,  9.],
               [10., 11., 12., 13., 14.],
               [15., 16., 17., 18., 19.],
               [20., 21., 22., 23., 24.]])
        >> fast_knn(data, k=1) # Weighted average (by distance) of nearest 1 neighbour
        array([[ 0.,  1.,  7.,  3.,  4.],
               [ 5.,  6.,  7.,  8.,  9.],
               [10., 11., 12., 13., 14.],
               [15., 16., 17., 18., 19.],
               [20., 21., 22., 23., 24.]])
        >> fast_knn(data, k=2) # Weighted average of nearest 2 neighbours
        array([[ 0.        ,  1.        , 10.08608891,  3.        ,  4.        ],
               [ 5.        ,  6.        ,  7.        ,  8.        ,  9.        ],
               [10.        , 11.        , 12.        , 13.        , 14.        ],
               [15.        , 16.        , 17.        , 18.        , 19.        ],
               [20.        , 21.        , 22.        , 23.        , 24.        ]])
        >> fast_knn(data, k=3)
        array([[ 0.        ,  1.        , 13.40249283,  3.        ,  4.        ],
               [ 5.        ,  6.        ,  7.        ,  8.        ,  9.        ],
               [10.        , 11.        , 12.        , 13.        , 14.        ],
               [15.        , 16.        , 17.        , 18.        , 19.        ],
               [20.        , 21.        , 22.        , 23.        , 24.        ]])
        >> fast_knn(data, k=5) # There are at most only 4 neighbours. Raises error
        ...
        IndexError: index 5 is out of bounds for axis 0 with size 5

    """

# Path: impyute/ops/matrix.py
# def nan_indices(data):
# def map_nd(fn, arr):
# def every_nd(fn, arr):
# 
# Path: impyute/ops/wrapper.py
# @wraps(fn)
# def wrapper(*args, **kwargs):
#     postprocess_fn = None
#     ## convert tuple to list so args can be modified
#     args = list(args)
#     ## Either make a copy or use a pointer to the original
#     if kwargs.get('inplace'):
#         args[0] = args[0]
#     else:
#         args[0] = args[0].copy()
# 
#     ## If input data is a dataframe then cast the input to an np.array
#     ## and set an indicator flag before continuing
#     pd_DataFrame = get_pandas_df()
#     if pd_DataFrame and isinstance(args[0], pd_DataFrame):
#         postprocess_fn = pd_DataFrame
#         args[0] = args[0].values
# 
#     ## function invokation
#     results = u.execute_fn_with_args_and_or_kwargs(fn, args, kwargs)
# 
#     ## cast the output back to a DataFrame.
#     if postprocess_fn is not None:
#         results = postprocess_fn(results)
# 
#     return results
# 
# Path: impyute/ops/inverse_distance_weighting.py
# def shepards(distances, power=2):
# def to_percentage(vec):
# 
# Path: impyute/imputation/cs/central_tendency.py
# @wrapper.wrappers
# @wrapper.checks
# def mean(data):
#     """ Substitute missing values with the mean of that column.
# 
#     Parameters
#     ----------
#     data: numpy.ndarray
#         Data to impute.
# 
#     Returns
#     -------
#     numpy.ndarray
#         Imputed data.
# 
#     """
#     nan_xy = matrix.nan_indices(data)
#     for x_i, y_i in nan_xy:
#         row_wo_nan = data[:, [y_i]][~np.isnan(data[:, [y_i]])]
#         new_value = np.mean(row_wo_nan)
#         data[x_i][y_i] = new_value
#     return data


# Path: impyute/imputation/cs/fast_knn.py
import numpy as np
from scipy.spatial import KDTree
from impyute.ops import matrix
from impyute.ops import wrapper
from impyute.ops import inverse_distance_weighting as idw
from . import mean

        >>> data[0][2] =  np.nan
        >>> data
        array([[ 0.,  1., nan,  3.,  4.],
               [ 5.,  6.,  7.,  8.,  9.],
               [10., 11., 12., 13., 14.],
               [15., 16., 17., 18., 19.],
               [20., 21., 22., 23., 24.]])
        >> fast_knn(data, k=1) # Weighted average (by distance) of nearest 1 neighbour
        array([[ 0.,  1.,  7.,  3.,  4.],
               [ 5.,  6.,  7.,  8.,  9.],
               [10., 11., 12., 13., 14.],
               [15., 16., 17., 18., 19.],
               [20., 21., 22., 23., 24.]])
        >> fast_knn(data, k=2) # Weighted average of nearest 2 neighbours
        array([[ 0.        ,  1.        , 10.08608891,  3.        ,  4.        ],
               [ 5.        ,  6.        ,  7.        ,  8.        ,  9.        ],
               [10.        , 11.        , 12.        , 13.        , 14.        ],
               [15.        , 16.        , 17.        , 18.        , 19.        ],
               [20.        , 21.        , 22.        , 23.        , 24.        ]])
        >> fast_knn(data, k=3)
        array([[ 0.        ,  1.        , 13.40249283,  3.        ,  4.        ],
               [ 5.        ,  6.        ,  7.        ,  8.        ,  9.        ],
               [10.        , 11.        , 12.        , 13.        , 14.        ],
               [15.        , 16.        , 17.        , 18.        , 19.        ],
               [20.        , 21.        , 22.        , 23.        , 24.        ]])
        >> fast_knn(data, k=5) # There are at most only 4 neighbours. Raises error
        ...
        IndexError: index 5 is out of bounds for axis 0 with size 5

    """

    nan_xy = matrix.nan_indices(data)