使用 BIgQuery 生成正态分布序列
Generate normally distributed series using BIgQuery
有没有办法在 BQ 中生成正态分布的序列?理想情况下指定分布的均值和标准差。
我找到了一种使用 Marsaglia polar method 的方法,但它并不理想,因为我不希望分布的极坐标而是生成一个遵循正态分布指定参数的数组。
提前谢谢你。
此查询为您提供以 0 为中心的正态分布的欧氏坐标。您可以同时调整均值(均值变量)或 sd(方差变量)和 x 轴值 (GENERATE_ARRAY(beginning,end,step)
) :
CREATE TEMPORARY FUNCTION normal(x FLOAT64)
RETURNS FLOAT64
LANGUAGE js AS """
var mean=0;
var variance=1;
var x0=1/(Math.sqrt(2*Math.PI*variance));
var x1=-Math.pow(x-mean,2)/(2*Math.pow(variance,2));
return x0*Math.pow(Math.E,x1);
""";
WITH numbers AS
(SELECT x FROM UNNEST(GENERATE_ARRAY(-10, 10,0.5)) AS x)
SELECT x, normal(x) as normal
FROM numbers;
为此,我使用了 "User Defined Funtions" [1]。当您想要另一个 SQL 表达式或当您想要使用 Java 脚本(就像我所做的那样)时,会使用它们。
注意:我用的是正态分布的概率密度函数,如果你想用另一个你需要改变变量x0,x1和return(我分开写的所以更清楚) .
在 BQ 中最简单的方法是创建自定义函数:
CREATE OR REPLACE FUNCTION
`your_project.functions.normal_distribution_pdf`
(x ANY TYPE, mu ANY TYPE, sigma ANY TYPE) AS (
(
SELECT
safe_divide(1,sigma * power(2 * ACOS(-1),0.5)) * exp(-0.5 * power(safe_divide(x-mu,sigma),2))
)
);
接下来你只需要应用函数:
with inputs as (
SELECT 1 as x, 0 as mu, 1 as sigma
union all
SELECT 1.5 as x, 1 as mu, 2 as sigma
union all
SELECT 2 as x , 2 as mu, 3 as sigma
)
SELECT x,
`your_project.functions.normal_distribution_pdf`(x, mu, sigma) as normal_pdf
from
inputs
前面的答案给出了正常rv的概率分布函数。在这里,我使用 'polar coordinates' 方法,在 BQ 标准 SQL 中修改以前的答案,以给出根据所需分布生成的随机数。该问题要求不使用极坐标,这是一个奇怪的要求,因为在生成正态分布随机数时不使用极坐标。
CREATE TEMPORARY FUNCTION rnorm ( mu FLOAT64, sigma FLOAT64 ) AS
(
(select mu + sigma*(sqrt( 2*abs(
log( RAND())
)
)
)*cos( 2*ACOS(-1)*RAND())
)
)
;
select
num ,
rnorm(-1, 5.3) as RAND_NORM
FROM UNNEST(GENERATE_ARRAY(1, 17) ) AS num
有没有办法在 BQ 中生成正态分布的序列?理想情况下指定分布的均值和标准差。 我找到了一种使用 Marsaglia polar method 的方法,但它并不理想,因为我不希望分布的极坐标而是生成一个遵循正态分布指定参数的数组。 提前谢谢你。
此查询为您提供以 0 为中心的正态分布的欧氏坐标。您可以同时调整均值(均值变量)或 sd(方差变量)和 x 轴值 (GENERATE_ARRAY(beginning,end,step)
) :
CREATE TEMPORARY FUNCTION normal(x FLOAT64)
RETURNS FLOAT64
LANGUAGE js AS """
var mean=0;
var variance=1;
var x0=1/(Math.sqrt(2*Math.PI*variance));
var x1=-Math.pow(x-mean,2)/(2*Math.pow(variance,2));
return x0*Math.pow(Math.E,x1);
""";
WITH numbers AS
(SELECT x FROM UNNEST(GENERATE_ARRAY(-10, 10,0.5)) AS x)
SELECT x, normal(x) as normal
FROM numbers;
为此,我使用了 "User Defined Funtions" [1]。当您想要另一个 SQL 表达式或当您想要使用 Java 脚本(就像我所做的那样)时,会使用它们。
注意:我用的是正态分布的概率密度函数,如果你想用另一个你需要改变变量x0,x1和return(我分开写的所以更清楚) .
在 BQ 中最简单的方法是创建自定义函数:
CREATE OR REPLACE FUNCTION
`your_project.functions.normal_distribution_pdf`
(x ANY TYPE, mu ANY TYPE, sigma ANY TYPE) AS (
(
SELECT
safe_divide(1,sigma * power(2 * ACOS(-1),0.5)) * exp(-0.5 * power(safe_divide(x-mu,sigma),2))
)
);
接下来你只需要应用函数:
with inputs as (
SELECT 1 as x, 0 as mu, 1 as sigma
union all
SELECT 1.5 as x, 1 as mu, 2 as sigma
union all
SELECT 2 as x , 2 as mu, 3 as sigma
)
SELECT x,
`your_project.functions.normal_distribution_pdf`(x, mu, sigma) as normal_pdf
from
inputs
前面的答案给出了正常rv的概率分布函数。在这里,我使用 'polar coordinates' 方法,在 BQ 标准 SQL 中修改以前的答案,以给出根据所需分布生成的随机数。该问题要求不使用极坐标,这是一个奇怪的要求,因为在生成正态分布随机数时不使用极坐标。
CREATE TEMPORARY FUNCTION rnorm ( mu FLOAT64, sigma FLOAT64 ) AS
(
(select mu + sigma*(sqrt( 2*abs(
log( RAND())
)
)
)*cos( 2*ACOS(-1)*RAND())
)
)
;
select
num ,
rnorm(-1, 5.3) as RAND_NORM
FROM UNNEST(GENERATE_ARRAY(1, 17) ) AS num