Dela via


series_fit_poly_fl()

Funktionen series_fit_poly_fl() är en användardefinierad funktion (UDF) som tillämpar en polynomregression på en serie. Den här funktionen tar en tabell som innehåller flera serier (dynamiska numeriska matriser) och genererar den bästa anpassningen av polynom i hög ordning för varje serie med polynomregression. Den här funktionen returnerar både polynomkoefficienterna och den interpolerade polynomen över seriens intervall.

Anteckning

  • Använd den interna funktionen series_fit_poly() i stället för funktionen som beskrivs i det här dokumentet. Den inbyggda funktionen har samma funktioner och är bättre för prestanda och skalbarhet. Det här dokumentet tillhandahålls endast i referenssyfte.
  • Använd den inbyggda funktionen series_fit_line()för linjär regression av en jämnt fördelad serie, som den skapats av operatorn make-series.

Förutsättningar

  • Python-plugin-programmet måste vara aktiverat i klustret. Detta krävs för den infogade Python som används i funktionen .

Syntax

T | invoke series_fit_poly_fl(, y_series, y_fit_series, fit_coeffGrad, [ x_series ], [ x_istime ])

Läs mer om syntaxkonventioner.

Parametrar

Namn Typ Obligatorisk Beskrivning
y_series string ✔️ Namnet på den indatatabellkolumn som innehåller den beroende variabeln. Det vill säger serien att passa.
y_fit_series string ✔️ Namnet på den kolumn som ska lagra serien med bäst passform.
fit_coeff string ✔️ Namnet på kolumnen som ska lagra de polynomkoefficienter som passar bäst.
Grad int ✔️ Polynomens ordning som krävs för att få plats. Till exempel 1 för linjär regression, 2 för kvadratisk regression och så vidare.
x_series string Namnet på kolumnen som innehåller den oberoende variabeln, d.v.s. x- eller tidsaxeln. Den här parametern är valfri och behövs bara för ojämnt fördelade serier. Standardvärdet är en tom sträng, eftersom x är redundant för regression av en jämnt fördelad serie.
x_istime bool Den här parametern behövs bara om x_series har angetts och det är en vektor för datetime.

Funktionsdefinition

Du kan definiera funktionen genom att antingen bädda in dess kod som en frågedefinierad funktion eller skapa den som en lagrad funktion i databasen enligt följande:

Definiera funktionen med hjälp av följande let-instruktion. Inga behörigheter krävs.

Viktigt

En let-instruktion kan inte köras på egen hand. Den måste följas av en tabelluttrycksinstrukator. Om du vill köra ett fungerande exempel på series_fit_poly_fl()kan du läsa Exempel.

let series_fit_poly_fl=(tbl:(*), y_series:string, y_fit_series:string, fit_coeff:string, degree:int, x_series:string='', x_istime:bool=False)
{
    let kwargs = bag_pack('y_series', y_series, 'y_fit_series', y_fit_series, 'fit_coeff', fit_coeff, 'degree', degree, 'x_series', x_series, 'x_istime', x_istime);
    let code = ```if 1:
        y_series = kargs["y_series"]
        y_fit_series = kargs["y_fit_series"]
        fit_coeff = kargs["fit_coeff"]
        degree = kargs["degree"]
        x_series = kargs["x_series"]
        x_istime = kargs["x_istime"]

        def fit(ts_row, x_col, y_col, deg):
            y = ts_row[y_col]
            if x_col == "": # If there is no x column creates sequential range [1, len(y)]
               x = np.arange(len(y)) + 1
            else: # if x column exists check whether its a time column. If so, normalize it to the [1, len(y)] range, else take it as is.
               if x_istime: 
                   x = pd.to_numeric(pd.to_datetime(ts_row[x_col]))
                   x = x - x.min()
                   x = x / x.max()
                   x = x * (len(x) - 1) + 1
               else:
                   x = ts_row[x_col]
            coeff = np.polyfit(x, y, deg)
            p = np.poly1d(coeff)
            z = p(x)
            return z, coeff

        result = df
        if len(df):
           result[[y_fit_series, fit_coeff]] = df.apply(fit, axis=1, args=(x_series, y_series, degree,), result_type="expand")
    ```;
    tbl
     | evaluate python(typeof(*), code, kwargs)
};
// Write your query to use the function here.

Exempel

I följande exempel används operatorn invoke för att köra funktionen.

Anpassa polynom i femte ordningen till en vanlig tidsserie

Om du vill använda en frågedefinierad funktion anropar du den efter den inbäddade funktionsdefinitionen.

let series_fit_poly_fl=(tbl:(*), y_series:string, y_fit_series:string, fit_coeff:string, degree:int, x_series:string='', x_istime:bool=False)
{
    let kwargs = bag_pack('y_series', y_series, 'y_fit_series', y_fit_series, 'fit_coeff', fit_coeff, 'degree', degree, 'x_series', x_series, 'x_istime', x_istime);
    let code = ```if 1:
        y_series = kargs["y_series"]
        y_fit_series = kargs["y_fit_series"]
        fit_coeff = kargs["fit_coeff"]
        degree = kargs["degree"]
        x_series = kargs["x_series"]
        x_istime = kargs["x_istime"]

        def fit(ts_row, x_col, y_col, deg):
            y = ts_row[y_col]
            if x_col == "": # If there is no x column creates sequential range [1, len(y)]
               x = np.arange(len(y)) + 1
            else: # if x column exists check whether its a time column. If so, normalize it to the [1, len(y)] range, else take it as is.
               if x_istime: 
                   x = pd.to_numeric(pd.to_datetime(ts_row[x_col]))
                   x = x - x.min()
                   x = x / x.max()
                   x = x * (len(x) - 1) + 1
               else:
                   x = ts_row[x_col]
            coeff = np.polyfit(x, y, deg)
            p = np.poly1d(coeff)
            z = p(x)
            return z, coeff

        result = df
        if len(df):
           result[[y_fit_series, fit_coeff]] = df.apply(fit, axis=1, args=(x_series, y_series, degree,), result_type="expand")
    ```;
    tbl
     | evaluate python(typeof(*), code, kwargs)
};
//
// Fit fifth order polynomial to a regular (evenly spaced) time series, created with make-series
//
let max_t = datetime(2016-09-03);
demo_make_series1
| make-series num=count() on TimeStamp from max_t-1d to max_t step 5m by OsVer
| extend fnum = dynamic(null), coeff=dynamic(null), fnum1 = dynamic(null), coeff1=dynamic(null)
| invoke series_fit_poly_fl('num', 'fnum', 'coeff', 5)
| render timechart with(ycolumns=num, fnum)

Resultat

Diagram som visar polynom i femte ordningen som passar en vanlig tidsserie.

Testa oregelbunden tidsserie

Om du vill använda en frågedefinierad funktion anropar du den efter den inbäddade funktionsdefinitionen.

let series_fit_poly_fl=(tbl:(*), y_series:string, y_fit_series:string, fit_coeff:string, degree:int, x_series:string='', x_istime:bool=False)
{
    let kwargs = bag_pack('y_series', y_series, 'y_fit_series', y_fit_series, 'fit_coeff', fit_coeff, 'degree', degree, 'x_series', x_series, 'x_istime', x_istime);
    let code = ```if 1:
        y_series = kargs["y_series"]
        y_fit_series = kargs["y_fit_series"]
        fit_coeff = kargs["fit_coeff"]
        degree = kargs["degree"]
        x_series = kargs["x_series"]
        x_istime = kargs["x_istime"]

        def fit(ts_row, x_col, y_col, deg):
            y = ts_row[y_col]
            if x_col == "": # If there is no x column creates sequential range [1, len(y)]
               x = np.arange(len(y)) + 1
            else: # if x column exists check whether its a time column. If so, normalize it to the [1, len(y)] range, else take it as is.
               if x_istime: 
                   x = pd.to_numeric(pd.to_datetime(ts_row[x_col]))
                   x = x - x.min()
                   x = x / x.max()
                   x = x * (len(x) - 1) + 1
               else:
                   x = ts_row[x_col]
            coeff = np.polyfit(x, y, deg)
            p = np.poly1d(coeff)
            z = p(x)
            return z, coeff

        result = df
        if len(df):
           result[[y_fit_series, fit_coeff]] = df.apply(fit, axis=1, args=(x_series, y_series, degree,), result_type="expand")
    ```;
    tbl
     | evaluate python(typeof(*), code, kwargs)
};
let max_t = datetime(2016-09-03);
demo_make_series1
| where TimeStamp between ((max_t-2d)..max_t)
| summarize num=count() by bin(TimeStamp, 5m), OsVer
| order by TimeStamp asc
| where hourofday(TimeStamp) % 6 != 0   //  delete every 6th hour to create unevenly spaced time series
| summarize TimeStamp=make_list(TimeStamp), num=make_list(num) by OsVer
| extend fnum = dynamic(null), coeff=dynamic(null)
| invoke series_fit_poly_fl('num', 'fnum', 'coeff', 8, 'TimeStamp', True)
| render timechart with(ycolumns=num, fnum)

Resultat

Diagram som visar den åttonde ordningens polynomanpassning till en oregelbunden tidsserie.

Polynom i femte ordningen med brus på x & y-axlar

Om du vill använda en frågedefinierad funktion anropar du den efter den inbäddade funktionsdefinitionen.

let series_fit_poly_fl=(tbl:(*), y_series:string, y_fit_series:string, fit_coeff:string, degree:int, x_series:string='', x_istime:bool=False)
{
    let kwargs = bag_pack('y_series', y_series, 'y_fit_series', y_fit_series, 'fit_coeff', fit_coeff, 'degree', degree, 'x_series', x_series, 'x_istime', x_istime);
    let code = ```if 1:
        y_series = kargs["y_series"]
        y_fit_series = kargs["y_fit_series"]
        fit_coeff = kargs["fit_coeff"]
        degree = kargs["degree"]
        x_series = kargs["x_series"]
        x_istime = kargs["x_istime"]

        def fit(ts_row, x_col, y_col, deg):
            y = ts_row[y_col]
            if x_col == "": # If there is no x column creates sequential range [1, len(y)]
               x = np.arange(len(y)) + 1
            else: # if x column exists check whether its a time column. If so, normalize it to the [1, len(y)] range, else take it as is.
               if x_istime: 
                   x = pd.to_numeric(pd.to_datetime(ts_row[x_col]))
                   x = x - x.min()
                   x = x / x.max()
                   x = x * (len(x) - 1) + 1
               else:
                   x = ts_row[x_col]
            coeff = np.polyfit(x, y, deg)
            p = np.poly1d(coeff)
            z = p(x)
            return z, coeff

        result = df
        if len(df):
           result[[y_fit_series, fit_coeff]] = df.apply(fit, axis=1, args=(x_series, y_series, degree,), result_type="expand")
    ```;
    tbl
     | evaluate python(typeof(*), code, kwargs)
};
range x from 1 to 200 step 1
| project x = rand()*5 - 2.3
| extend y = pow(x, 5)-8*pow(x, 3)+10*x+6
| extend y = y + (rand() - 0.5)*0.5*y
| summarize x=make_list(x), y=make_list(y)
| extend y_fit = dynamic(null), coeff=dynamic(null)
| invoke series_fit_poly_fl('y', 'y_fit', 'coeff', 5, 'x')
|fork (project-away coeff) (project coeff | mv-expand coeff)
| render linechart

Resultat

Diagram över anpassning av polynom i femte ordningen med brus på x & y-axlar

Koefficienter av passform av femte ordningen polynom med brus.

Den här funktionen stöds inte.