2012-01-18 6 views
6

tôi cần sự giúp đỡ trong những điều sau đây: Tôi có một tệp dữ liệu (cột cách nhau dấu "\ t" bảng) như thế này data.datPhép ngoại suy - awk dựa

# y1 y2  y3  y4 
    17.1685 21.6875 20.2393 26.3158 

Đây là những giá trị của x 4 điểm cho một tuyến tính Phù hợp. Bốn giá trị y là hằng số: 0, 200, 400, 600.

Tôi có thể tạo sự phù hợp tuyến tính của các cặp điểm (x,y): (x1,y1)=(17.1685,0), (x2,y2)=(21.6875,200), (x3,y3)=(20.2393,400), (x4,y4)=(26.3158,600).

Bây giờ tôi muốn thực hiện một sự phù hợp tuyến tính trên ba trong số những điểm paris, (x1,y1), (x2,y2), (x3,y3) and (x2,y2), (x3,y3), (x4,y4) and (x1,y1), (x3,y3), (x4,y4) and (x1,y1), (x2,y2), (x4,y4).

Nếu tôi có ba điểm với một sự phù hợp tuyến tính Tôi muốn biết giá trị của x giá trị của ngoại suy điểm ra khỏi ba điểm được trang bị này.

tôi có cho đến nay đang awk này:

#!/usr/bin/awk -f 

BEGIN{ 
    z[1] = 0; 
    z[2] = 200; 
    z[3] = 400; 
    z[4] = 600; 
} 

{ 
    split($0,str,"\t"); 
    n = 0.0; 

    for(i=1; i<=NF; i++) 
    { 
    centr[i] = str[i]; 
    n += 1.0; 
    # printf("%d\t%f\t%.1f\t",i,centr[i],z[i]); 
    } 
    # print ""; 

    if (n > 2) 
    { 
    lsq(n,z,centr); 
    } 
} 

function lsq(n,x,y) 
{ 
    sx = 0.0 
    sy = 0.0 
    sxx = 0.0 
    syy = 0.0 
    sxy = 0.0 
    eps = 0.0 

    for (i=1;i<=n;i++) 
    { 
    sx += x[i] 
    sy += y[i] 
    sxx += x[i]*x[i] 
    sxy += x[i]*y[i] 
    syy += y[i]*y[i] 
    } 

    if ((n==0) || ((n*sxx-sx*sx)==0)) 
    { 
    next; 
    } 
# print "number of data points = " n; 
    a = (sxx*sy-sxy*sx)/(n*sxx-sx*sx) 
    b = (n*sxy-sx*sy)/(n*sxx-sx*sx) 

    for(i=1;i<=n;i++) 
    { 
    ycalc[i] = a+b*x[i] 
    dy[i] = y[i]-ycalc[i] 
    eps  += dy[i]*dy[i] 
    } 

    print "# Intercept =\t"a" 
    print "# Slope  =\t"b" 

    for (i=1;i<=n;i++) 
    { 
    printf("%8g %8g %8g \n",x[i],y[i],ycalc[i]) 
    } 

} # function lsq() 

Vì vậy,

If we extrapolate to the place of 4th 
    0 17.1685 <--(x1,y1) 
    200 21.6875 <--(x2,y2) 
    400 20.2393 <--(x3,y3) 
    600 22.7692 <<< (x4 = 600,y1 = 22.7692) 

    If we extrapolate to the place of 3th 
    0 17.1685 <--(x1,y1) 
    200 21.6875 <--(x2,y2) 
    400 23.6867 <<< (x3 = 400,y3 = 23.6867) 
    600 26.3158 <--(x4,y4) 

    0 17.1685 
    200 19.35266 <<< 
    400 20.2393 
    600 26.3158 

    0 18.1192 <<< 
    200 21.6875 
    400 20.2393 
    600 26.3158 

sản lượng hiện tại của tôi là như sau:

$> ./prog.awk data.dat 
# Intercept = 17.4537 
# Slope  = 0.0129968 
     0 17.1685 17.4537 
    200 21.6875 20.0531 
    400 20.2393 22.6525 
    600 26.3158 25.2518 
+2

Không phải là giá trị của hằng số 'y'? Làm thế nào họ có được đổi chỗ? –

Trả lời

4

Giả sử tính toán cốt lõi trong lsq chức năng là OK (có vẻ đúng, nhưng tôi đã không xem xét nó), sau đó cung cấp cho bạn độ dốc và tôi ntercept cho tổng số ít nhất của đường bình phương phù hợp nhất cho tập dữ liệu đầu vào (tham số x, y, n). Tôi không chắc tôi hiểu phần đuôi của hàm.

Đối với 'lấy ba điểm và tính toán vấn đề thứ tư', cách đơn giản nhất là tạo 4 tập hợp con (một cách hợp lý, bằng cách xóa một điểm khỏi nhóm bốn trong bốn cuộc gọi) và làm lại phép tính.

Bạn cần gọi một hàm khác có dữ liệu đường thẳng (độ dốc, chặn) từ lsq và nội suy (ngoại suy) giá trị ở giá trị y khác. Đó là một tính thẳng về phía trước (x = m * y + c), nhưng bạn cần phải xác định y giá trị là mất tích từ bộ 3 bạn vượt qua trong.

Bạn có thể 'tối ưu hóa' (nghĩa là 'phức tạp') chương trình này bằng cách thả một giá trị tại một thời điểm từ các giá trị 'tổng các bình phương' và 'tổng' và 'tổng giá trị sản phẩm', tính toán lại độ dốc, chặn, và sau đó tính lại điểm bị thiếu.

(Tôi cũng sẽ quan sát rằng thông thường nó sẽ là tọa độ x với các giá trị cố định 0, 200, 400, 600 và tọa độ y sẽ là giá trị được đọc. Tuy nhiên, đó chỉ là vấn đề định hướng, vì vậy nó không quan trọng.)


Đây là ít nhất mã làm việc hợp lý. Kể từ khi awk tự động chia tách trên không gian trắng, bạn không cần phải phân tách trên các tab cụ thể; vòng lặp đọc sẽ tính đến điều này.

Mã cần tái cấu trúc nghiêm trọng; có rất nhiều sự lặp lại trong nó - tuy nhiên, tôi cũng có một công việc mà tôi phải làm.

#!/usr/bin/awk -f 
BEGIN{ 
    z[1] = 0; 
    z[2] = 200; 
    z[3] = 400; 
    z[4] = 600; 
} 

{ 
    for (i = 1; i <= NF; i++) 
    { 
    centr[i] = $i 
    } 

    if (NF > 2) 
    { 
    lsq(NF, z, centr); 
    } 
} 

function lsq(n, x, y) 
{ 
    if (n == 0) return 

    sx = 0.0 
    sy = 0.0 
    sxx = 0.0 
    syy = 0.0 
    sxy = 0.0 

    for (i = 1; i <= n; i++) 
    { 
    print "x[" i "] = " x[i] ", y[" i "] = " y[i] 
    sx += x[i] 
    sy += y[i] 
    sxx += x[i]*x[i] 
    sxy += x[i]*y[i] 
    syy += y[i]*y[i] 
    } 

    if ((n*sxx - sx*sx) == 0) return 

# print "number of data points = " n; 
    a = (sxx*sy-sxy*sx)/(n*sxx-sx*sx) 
    b = (n*sxy-sx*sy)/(n*sxx-sx*sx) 

    for (i = 1; i <= n; i++) 
    { 
    ycalc[i] = a+b*x[i] 
    } 

    print "# Intercept = " a 
    print "# Slope  = " b 
    print "Line: x = " a " + " b " * y" 

    for (i = 1; i <= n; i++) 
    { 
    printf("x = %8g, yo = %8g, yc = %8g\n", x[i], y[i], ycalc[i]) 
    } 

    print "" 
    print "Different subsets\n" 

    for (drop = 1; drop <= n; drop++) 
    { 
    print "Subset " drop 
    sx = sy = sxx = sxy = syy = 0 
    j = 1 
    for (i = 1; i <= n; i++) 
    { 
     if (i == drop) continue 
     print "x[" j "] = " x[i] ", y[" j "] = " y[i] 
     sx += x[i] 
     sy += y[i] 
     sxx += x[i]*x[i] 
     sxy += x[i]*y[i] 
     syy += y[i]*y[i] 
     j++ 
    } 
    if (((n-1)*sxx - sx*sx) == 0) continue 
    a = (sxx*sy-sxy*sx)/((n-1)*sxx-sx*sx) 
    b = ((n-1)*sxy-sx*sy)/((n-1)*sxx-sx*sx) 
    print "Line: x = " a " + " b " * y" 

    xt = x[drop] 
    yt = a + b * xt; 
    print "Interpolate: x = " xt ", y = " yt 
    } 
} 

Kể từ awk không cung cấp một cách dễ dàng để vượt qua trở lại nhiều giá trị từ một hàm, cũng không cung cấp các cấu trúc khác so với mảng (đôi khi kết hợp), nó không phải là có lẽ là ngôn ngữ tốt nhất cho nhiệm vụ này. Mặt khác, nó có thể được thực hiện để thực hiện công việc. Bạn có thể gộp tính toán Hình vuông tối thiểu trong một hàm trả về một mảng chứa độ dốc và chặn, sau đó sử dụng nó. Đến lượt bạn khám phá các tùy chọn.

Với kịch bản lsq.awk và các tập tin đầu vào lsq.data hiển thị, tôi nhận được đầu ra cho thấy:

$ cat lsq.data 
17.1685 21.6875 20.2393 26.3158 
$ awk -f lsq.awk lsq.data 
x[1] = 0, y[1] = 17.1685 
x[2] = 200, y[2] = 21.6875 
x[3] = 400, y[3] = 20.2393 
x[4] = 600, y[4] = 26.3158 
# Intercept = 17.4537 
# Slope  = 0.0129968 
Line: x = 17.4537 + 0.0129968 * y 
x =  0, yo = 17.1685, yc = 17.4537 
x =  200, yo = 21.6875, yc = 20.0531 
x =  400, yo = 20.2393, yc = 22.6525 
x =  600, yo = 26.3158, yc = 25.2518 

Different subsets 

Subset 1 
x[1] = 200, y[1] = 21.6875 
x[2] = 400, y[2] = 20.2393 
x[3] = 600, y[3] = 26.3158 
Line: x = 18.1192 + 0.0115708 * y 
Interpolate: x = 0, y = 18.1192 
Subset 2 
x[1] = 0, y[1] = 17.1685 
x[2] = 400, y[2] = 20.2393 
x[3] = 600, y[3] = 26.3158 
Line: x = 16.5198 + 0.0141643 * y 
Interpolate: x = 200, y = 19.3526 
Subset 3 
x[1] = 0, y[1] = 17.1685 
x[2] = 200, y[2] = 21.6875 
x[3] = 600, y[3] = 26.3158 
Line: x = 17.7985 + 0.0147205 * y 
Interpolate: x = 400, y = 23.6867 
Subset 4 
x[1] = 0, y[1] = 17.1685 
x[2] = 200, y[2] = 21.6875 
x[3] = 400, y[3] = 20.2393 
Line: x = 18.163 + 0.007677 * y 
Interpolate: x = 600, y = 22.7692 
$ 

Sửa: Trong các phiên bản trước của câu trả lời, các tập con được nhân với n thay vì (n-1). Các giá trị trong đầu ra được sửa đổi dường như đồng ý với những gì bạn mong đợi. Các vấn đề còn lại là hiện tại, không tính toán.

+0

Vâng, điều này có vẻ rõ ràng. Nhưng tôi không thể thực hiện nó cho đến nay .. Bạn có thể giúp tôi để hiển thị những chức năng, và mã số bạn đang suy nghĩ về? Phần nào cần được chỉnh sửa và làm cách nào? – user1116360

+0

Xin chào, có điều gì đó sai với mã bạn đã trình bày ... Ngay trong một vài hàng đầu tiên của đầu ra, ví dụ: Dòng: x = 5.43577 + 0.0387496 * y không đúng ..., phải là x = 18.1192 + 0.0115708 * y, phải không? – user1116360

+0

Tôi đã sửa đổi bài đăng với đầu ra yêu cầu chính xác – user1116360