Smooth a :class:`pandas.DataFrame` according to a window, weighting based on
    uncertainties.

    Arguments are:

    window
      The smoothing window.
    df
      The :class:`pandas.DataFrame`.
    ucol
      The name of the column in *df* that contains the uncertainties to weight
      by.
    k = None
      If specified, only every *k*-th point of the results will be kept. If k
      is None (the default), it is set to ``window.size``, i.e. correlated
      points will be discarded.

    Returns: a smoothed data frame.

    The returned data frame has a default integer index.

    Example::

        sdata = numutil.dfsmooth (np.hamming (7), data, 'u_temp')

def dfsmooth (window, df, ucol, k=None):
    """Smooth a :class:`pandas.DataFrame` according to a window, weighting based on
    uncertainties.

    Arguments are:

    window
      The smoothing window.
    df
      The :class:`pandas.DataFrame`.
    ucol
      The name of the column in *df* that contains the uncertainties to weight
      by.
    k = None
      If specified, only every *k*-th point of the results will be kept. If k
      is None (the default), it is set to ``window.size``, i.e. correlated
      points will be discarded.

    Returns: a smoothed data frame.

    The returned data frame has a default integer index.

    Example::

        sdata = numutil.dfsmooth (np.hamming (7), data, 'u_temp')

    """
    import pandas as pd

    if k is None:
        k = window.size

    conv = lambda q, r: np.convolve (q, r, mode='valid')
    w = df[ucol] ** -2
    invcw = 1. / conv (w, window)

    # XXX: we're not smoothing the index.

    res = {}

    for col in df.columns:
        if col == ucol:
            res[col] = np.sqrt (conv (w, window**2)) * invcw
        else:
            res[col] = conv (w * df[col], window) * invcw

    res = pd.DataFrame (res)
    return res[::k]