DataFrame.interpolate () extrapoliert fehlende Daten nach

Betrachten Sie das folgende Beispiel, in dem wir ein Beispiel-Dataset einrichten, einen MultiIndex erstellen, den Datenrahmen entstapeln und dann eine lineare Interpolation ausführen, bei der wir zeilenweise füllen:

import pandas as pd  # version 0.14.1
import numpy as np  # version 1.8.1

df = pd.DataFrame({'location': ['a', 'b'] * 5,
                   'trees': ['oaks', 'maples'] * 5,
                   'year': range(2000, 2005) * 2,
                   'value': [np.NaN, 1, np.NaN, 3, 2, np.NaN, 5, np.NaN, np.NaN, np.NaN]})
df.set_index(['trees', 'location', 'year'], inplace=True)
df = df.unstack()
df = df.interpolate(method='linear', axis=1)

Wo das nicht gestapelte Dataset so aussieht:

                 value                        
year              2000  2001  2002  2003  2004
trees  location                               
maples b           NaN     1   NaN     3   NaN
oaks   a           NaN     5   NaN   NaN     2

Als einInterpolation Methode erwarte ich die Ausgabe:

                 value                        
year              2000  2001  2002  2003  2004
trees  location                               
maples b           NaN     1     2     3   NaN
oaks   a           NaN     5     4     3     2

Stattdessen liefert die Methode (beachten Sie den extrapolierten Wert):

                 value                        
year              2000  2001  2002  2003  2004
trees  location                               
maples b           NaN     1     2     3     3
oaks   a           NaN     5     4     3     2

Gibt es eine Möglichkeit, Pandas anzuweisen, nicht über den letzten nicht fehlenden Wert in einer Reihe hinaus zu extrapolieren?

BEARBEITEN:

Ich würde diese Funktionalität immer noch gerne in Pandas sehen, aber im Moment habe ich sie als Funktion in Numpy implementiert und benutze sie danndf.apply() um das zu änderndf. Es war die Funktionalität desleft undright Parameter innp.interp() das habe ich bei Pandas verpasst.

def interpolate(a, dec=None):
    """
    :param a: a 1d array to be interpolated
    :param dec: the number of decimal places with which each
                value should be returned
    :return: returns an array of integers or floats
    """

    # default value is the largest number of decimal places in the input array
    if dec is None:
        dec = max_decimal(a)

    # detect array format convert to numpy as necessary
    if type(a) == list:
        t = 'list'
        b = np.asarray(a, dtype='float')
    if type(a) in [pd.Series, np.ndarray]:
        b = a

    # return the row if it's all nan's
    if np.all(np.isnan(b)):
        return a

    # interpolate
    x = np.arange(b.size)
    xp = np.where(~np.isnan(b))[0]
    fp = b[xp]
    interp = np.around(np.interp(x, xp, fp, np.nan, np.nan), decimals=dec)

    # return with proper numerical type formatting
    # check to make sure there aren't nan's before converting to int
    if dec == 0 and np.isnan(np.sum(interp)) == False:
        interp = interp.astype(int)
    if t == 'list':
        return interp.tolist()
    else:
        return interp


# two little helper functions
def count_decimal(i):
    try:
        return int(decimal.Decimal(str(i)).as_tuple().exponent) * -1
    except ValueError:
        return 0


def max_decimal(a):
    m = 0
    for i in a:
        n = count_decimal(i)
        if n > m:
            m = n
    return m

Funktioniert wie ein Zauber auf dem Beispieldatensatz:

In[1]: df.apply(interpolate, axis=1)
Out[1]:
                 value                        
year              2000  2001  2002  2003  2004
trees  location                               
maples b           NaN     1     2     3   NaN
oaks   a           NaN     5     4     3     2

Antworten auf die Frage(3)

Ihre Antwort auf die Frage