Kdb+中如何从linearLL生成的lr列提取截距与斜率?
问题描述
我定义了以下KDB+线性回归函数:
// linear regression y vs x // returns: intercept slope linear:{ if[not (count x)=(count y); show "x and y must have the same length"; exit 1]; fit:{(enlist x) lsq y xexp/:til 1+z}; fit[x; y; 1] }; // takes X and Y as a list of lists linearLL:{[X;Y] t:([] x:X; y:Y); raze {9h$linear[x`x; x`y]} each t}; \d .
基于滑动窗口生成表t后,通过.regression.linearLL[x;y]得到lr列,表内容如下:
p time x y lr ------------------------------------------ 1 2024.01.01 ,0f ,1f 2 2024.01.02 0 1f 1 2f -1 1 3 2024.01.03 0 1 2f 1 2 3f -1 1 4 2024.01.07 0 1 2 6f 1 2 3 4f -2.5 1.9 5 2024.01.08 1 2 6 7f 2 3 4 5f -3.7 2.2 6 2024.01.10 2 6 7 9f 3 4 5 6f -3.9 2.2 7 2024.01.14 6 7 9 13f 4 5 6 7f -3.9 2.3 8 2024.01.15 7 9 13 14f 5 6 7 8f -5.5 2.5 9 2024.01.16 9 13 14 15f 6 7 8 9f -1.5 1.9
执行show t:update intercept:lr[0], slope:lr[1] from t;时触发'length错误,推测lr元素应为二元列表但实际并非如此,请问如何提取截距和斜率?
解决方案
错误原因
linearLL函数中的raze会将每个linear返回的二元结果扁平化,导致lr列是一维长列表(长度为2×表行数),而非每行对应一个二元列表。此时lr[0]取的是整个列的第一个元素,无法匹配表的行数,从而引发长度错误。
方法一:修正linearLL函数(推荐)
移除raze,让函数返回二元float向量的列表,每行对应一组截距和斜率:
linearLL:{[X;Y] t:([] x:X; y:Y); {9h$linear[x`x; x`y]} each t};
之后即可用以下代码提取截距和斜率:
// 方式1:用each遍历每行取首尾元素 t:update intercept:first each lr, slope:last each lr from t; // 方式2:直接索引向量的第0、1位 t:update intercept:lr[;0], slope:lr[;1] from t;
方法二:从扁平化的lr列中提取(不修改函数时用)
如果lr列已是扁平化结构,可通过步长索引提取对应位置的元素:
// 通用写法,自动匹配表行数 t:update intercept:lr[2*til count t], slope:lr[1+2*til count t] from t;
注:若第一行lr为空,需先处理空值,比如用where not null lr筛选有效索引后再提取。
内容的提问来源于stack exchange,提问作者marital_weeping
相关产品推荐
相关产品推荐

