ใครบ้างมีฟังก์ชั่นการถดถอยของ Theil-Senเขียนใน T-SQL?
ฉันพบหนึ่งเขียนใน Perlแต่ฉันไม่สามารถ recode ลงใน SQL
ใครบ้างมีฟังก์ชั่นการถดถอยของ Theil-Senเขียนใน T-SQL?
ฉันพบหนึ่งเขียนใน Perlแต่ฉันไม่สามารถ recode ลงใน SQL
คำตอบ:
ฉันโกหกเมื่อฉันบอกว่าฉันไม่สามารถบันทึกเป็น SQL ได้ ฉันขี้เกียจเกินไป นี่คือรหัสพร้อมตัวอย่างการใช้งาน
รหัสจะขึ้นอยู่กับTheisen Perl ห้องสมุดใช้QuickMedian ลองกำหนดประเภทตารางใหม่เพื่อส่งผ่านข้อมูลของเราไปยังกระบวนการ
CREATE TYPE dbo.TheilSenInputDataTableType AS TABLE
(
ID INT IDENTITY(1,1),
x REAL,
y REAL
)
โปรดทราบคอลัมน์ ID ซึ่งเป็นสิ่งสำคัญที่นี่เนื่องจากวิธีการแก้ปัญหาของเราใช้คำสั่ง CROSS APPLY เพื่อให้การตีความวงในที่ถูกต้องใน TheilSen.pm ถูกต้อง
my ($x1,$x2,$y1,$y2);
foreach my $i(0 .. $n-2){
$y1 = $y->[$i];
$x1 = $x->[$i];
foreach my $j($i+1 .. $n-1){
$y2 = $y->[$j];
$x2 = $x->[$j];
นอกจากนี้เรายังต้องใช้ชนิดข้อมูลใหม่สำหรับการจัดเก็บค่าประเภทจริงมากมาย
CREATE TYPE [dbo].[RealArray] AS TABLE(
[val] [real] NULL
)
นี่คือฟังก์ชันf_QuickMedianส่งคืนค่ามัธยฐานสำหรับอาร์เรย์ที่ระบุ สินเชื่อเพื่อการนี้ไปItzik เบนกาน
CREATE FUNCTION [dbo].[f_QuickMedian](@RealArray RealArray READONLY)
RETURNS REAL
AS
BEGIN
DECLARE @Median REAL;
DECLARE @QMedian REAL;
SELECT @Median = AVG(1.0 * val)
FROM
(
SELECT o.val, rn = ROW_NUMBER() OVER (ORDER BY o.val), c.c
FROM @RealArray AS o
CROSS JOIN (SELECT c = COUNT(*) FROM @RealArray) AS c
) AS x
WHERE rn IN ((c + 1)/2, (c + 2)/2);
SELECT TOP 1 @QMedian = val FROM @RealArray
ORDER BY ABS(val - @Median) ASC, val DESC
RETURN @QMedian
END
และตัวประมาณp_TheilSen :
CREATE PROCEDURE [dbo].[p_TheilSen](
@TheilSenInput TheilSenInputDataTableType READONLY
, @m Real OUTPUT
, @c Real OUTPUT
)
AS
BEGIN
DECLARE
@m_arr RealArray
, @c_arr RealArray;
INSERT INTO @m_arr
SELECT m
FROM
(
SELECT
t1.x as x1
, t1.y as y1
, t2o.x as x2
, t2o.y as y2
, t2o.y-t1.y as [y2 - y1]
, t2o.x-t1.x as [x2 - x1]
, CASE WHEN (t2o.x <> t1.x) THEN CAST((t2o.y-t1.y) AS Real)/(t2o.x-t1.x) ELSE NULL END AS [($y2-$y1)/($x2-$x1)]
, CASE WHEN t1.y = t2o.y THEN 0
ELSE
CASE WHEN t1.x = t2o.x THEN NULL
ELSE
-- push @M, ($y2-$y1)/($x2-$x1);
CAST((t2o.y-t1.y) AS Real)/(t2o.x-t1.x)
END
END as m
FROM @TheilSenInput t1
CROSS APPLY
(
SELECT t2.x, t2.y
FROM @TheilSenInput t2
WHERE t2.ID > t1.ID
) t2o
) t
WHERE m IS NOT NULL
SELECT @m = dbo.f_QuickMedian(@m_arr)
INSERT INTO @c_arr
SELECT y - (@m * x)
FROM @TheilSenInput
SELECT @c = dbo.f_QuickMedian(@c_arr)
END
ตัวอย่าง:
DECLARE
@in TheilSenInputDataTableType
, @m Real
, @c Real
INSERT INTO @in(x,y) VALUES (10.79,118.99)
INSERT INTO @in(x,y) VALUES (10.8,120.76)
INSERT INTO @in(x,y) VALUES (10.86,122.71)
INSERT INTO @in(x,y) VALUES (10.93,125.48)
INSERT INTO @in(x,y) VALUES (10.99,127.31)
INSERT INTO @in(x,y) VALUES (10.96,130.06)
INSERT INTO @in(x,y) VALUES (10.98,132.41)
INSERT INTO @in(x,y) VALUES (11.03,135.89)
INSERT INTO @in(x,y) VALUES (11.08,139.02)
INSERT INTO @in(x,y) VALUES (11.1,140.25)
INSERT INTO @in(x,y) VALUES (11.19,145.61)
INSERT INTO @in(x,y) VALUES (11.25,153.45)
INSERT INTO @in(x,y) VALUES (11.4,158.03)
INSERT INTO @in(x,y) VALUES (11.61,162.72)
INSERT INTO @in(x,y) VALUES (11.69,167.67)
INSERT INTO @in(x,y) VALUES (11.91,172.86)
INSERT INTO @in(x,y) VALUES (12.07,177.52)
INSERT INTO @in(x,y) VALUES (12.32,182.09)
EXEC p_TheilSen @in, @m = @m OUTPUT, @c = @c OUTPUT
SELECT @m
SELECT @c
ผลตอบแทน:
m = 52.7079
c = -448.4853
เพียงเพื่อการเปรียบเทียบรุ่น perl คืนค่าต่อไปนี้สำหรับชุดข้อมูลเดียวกัน:
m = 52.7078651685394
c = -448.484943820225
ฉันใช้ตัวประเมิน TheilSen เพื่อคำนวณตัวชี้วัด DaysToFill สำหรับระบบไฟล์ สนุก!
สิ่งนี้น่าจะเหมาะกับการทำอะไรบางอย่างใน SQLCLR คล้ายกับคำถาม / คำตอบต่อไปนี้ (เช่นที่ DBA.SE):
มีการใช้ SQL Server ของปัญหา Substring ทั่วไปที่ยาวที่สุด?
เมื่อฉันมีเวลาในภายหลังฉันจะเห็นว่าความเป็นไปได้นี้จะเป็นอย่างไร
ฉันตรวจสอบแล้วสำหรับ T-SQL, Oracle และเซิร์ฟเวอร์โดยทั่วไป (ซับซ้อนเกินไปที่จะเขียนใน SQL บริสุทธิ์)
อย่างไรก็ตามคุณอาจสนใจสิ่งนี้ (แพ็คเกจทางวิทยาศาสตร์ / สถิติสำหรับ Python) อัลกอริทึมจะดำเนินการที่นั่นและในหลาม Python เป็นภาษาที่มนุษย์มีโอกาสอย่างน้อยที่จะสามารถเข้าใจได้ซึ่งแตกต่างจาก Perl
คำถามของคุณทำให้ฉันทึ่งและฉันก็ขุดไปรอบ ๆ มีไลบรารี C และ C ++ ซึ่งมีอัลกอริทึมนี้ - และยังมีอยู่ในแพ็คเกจ R สองสามชุด และโพสต์ของ @srutzky ก็ดูน่าสนใจเช่นกัน
+1 สำหรับคำถามที่น่าสนใจ BTW - และยินดีต้อนรับสู่ฟอรัม :-)