Javascript 如何使用BigQuery查找置信区间?

Javascript 如何使用BigQuery查找置信区间?,javascript,google-bigquery,Javascript,Google Bigquery,我有两个JavaScript函数通过二项测试计算置信区间。当我将其作为任何js代码运行时,这两种方法都能很好地工作。 当我将其集成到查询第二个函数中以查找置信区间上限时,返回NaN。我不明白为什么它在BigQuery中不起作用 CREATE TEMP FUNCTION findConfidenceIntervalFloor(C INT64, L INT64, p FLOAT64) RETURNS FLOAT64 LANGUAGE js AS """ functi

我有两个JavaScript函数通过二项测试计算置信区间。当我将其作为任何js代码运行时,这两种方法都能很好地工作。 当我将其集成到查询第二个函数中以查找置信区间上限时,返回NaN。我不明白为什么它在BigQuery中不起作用

CREATE TEMP FUNCTION findConfidenceIntervalFloor(C INT64, L INT64, p FLOAT64)
RETURNS FLOAT64
LANGUAGE js AS """
  function binomial_test(k, n, p){
    if(k < 0 || k > n || n <= 0 || p < 0 || p > 1) return NaN;
    // i = 0 term
    var logcoef = 0;
    var pvalue = Math.pow(Math.E, n*Math.log(1-p)); // Math.exp is not available
    // i > 0 terms
    for(var i = 1; i <= k; i++) {
      logcoef = logcoef + Math.log(n-i+1) - Math.log(i);
      pvalue = pvalue + Math.pow(Math.E, logcoef + i*Math.log(p) + (n-i)*Math.log(1-p));
    }
    return pvalue;
  }
  let CR = L/C
    let x1 = 0
    let x2 = L   
    while ((x2 - x1) > 1) {       
        let x = Math.ceil((x2 - x1) / 2 + x1)
        
        if (binomial_test(x, C, CR) < p/2) {
            x1 = x
        } else {
            x2 = x
        }
        
    }
    return x2;
  """;

CREATE TEMP FUNCTION findConfidenceIntervalCeil(C INT64, L INT64, p FLOAT64)
RETURNS FLOAT64
LANGUAGE js AS """
  function binomial_test(k, n, p){
    if(k < 0 || k > n || n <= 0 || p < 0 || p > 1) return NaN;
    var logcoef = 0;
    var pvalue = Math.pow(Math.E, n*Math.log(1-p)); 
    for(var i = 1; i <= k; i++) {
      logcoef = logcoef + Math.log(n-i+1) - Math.log(i);
      pvalue = pvalue + Math.pow(Math.E, logcoef + i*Math.log(p) + (n-i)*Math.log(1-p));
    }
    return pvalue;
  }
  let CR = L/C;
    let x1 = L;
    let x2 = C;  
    while ((x2 - x1) > 1) {       
        let x = Math.ceil((x2 - x1) / 2 + x1);
        
        if (binomial_test(x, C, CR) < (1 - p/2)) {
            x1 = x;
        } else {
            x2 = x;
        }        
    }
    return x1;
  """;
WITH t0 as (SELECT 'site1' as name, 97000 as clicks, 3784 as leads
UNION ALL
SELECT 'site2', 68099, 2342)
  
select *, 
findConfidenceIntervalFloor(clicks, leads, 0.005) as bot_interval_del,
findConfidenceIntervalCeil(clicks, leads, 0.005) as top_interval_del,
findConfidenceIntervalFloor(clicks, leads, 0.05) as bot_interval_add,
findConfidenceIntervalCeil(clicks, leads, 0.05) as top_interval_add
from t0
现在我用强力除以2。我认为这不是计算它的最佳方法,所以有没有关于如何改进这一点的建议,至少让它在BigQuery中可行

CREATE TEMP FUNCTION findConfidenceIntervalFloor(C INT64, L INT64, p FLOAT64)
RETURNS FLOAT64
LANGUAGE js AS """
  function binomial_test(k, n, p){
    if(k < 0 || k > n || n <= 0 || p < 0 || p > 1) return NaN;
    // i = 0 term
    var logcoef = 0;
    var pvalue = Math.pow(Math.E, n*Math.log(1-p)); // Math.exp is not available
    // i > 0 terms
    for(var i = 1; i <= k; i++) {
      logcoef = logcoef + Math.log(n-i+1) - Math.log(i);
      pvalue = pvalue + Math.pow(Math.E, logcoef + i*Math.log(p) + (n-i)*Math.log(1-p));
    }
    return pvalue;
  }
  let CR = L/C
    let x1 = 0
    let x2 = L   
    while ((x2 - x1) > 1) {       
        let x = Math.ceil((x2 - x1) / 2 + x1)
        
        if (binomial_test(x, C, CR) < p/2) {
            x1 = x
        } else {
            x2 = x
        }
        
    }
    return x2;
  """;

CREATE TEMP FUNCTION findConfidenceIntervalCeil(C INT64, L INT64, p FLOAT64)
RETURNS FLOAT64
LANGUAGE js AS """
  function binomial_test(k, n, p){
    if(k < 0 || k > n || n <= 0 || p < 0 || p > 1) return NaN;
    var logcoef = 0;
    var pvalue = Math.pow(Math.E, n*Math.log(1-p)); 
    for(var i = 1; i <= k; i++) {
      logcoef = logcoef + Math.log(n-i+1) - Math.log(i);
      pvalue = pvalue + Math.pow(Math.E, logcoef + i*Math.log(p) + (n-i)*Math.log(1-p));
    }
    return pvalue;
  }
  let CR = L/C;
    let x1 = L;
    let x2 = C;  
    while ((x2 - x1) > 1) {       
        let x = Math.ceil((x2 - x1) / 2 + x1);
        
        if (binomial_test(x, C, CR) < (1 - p/2)) {
            x1 = x;
        } else {
            x2 = x;
        }        
    }
    return x1;
  """;
WITH t0 as (SELECT 'site1' as name, 97000 as clicks, 3784 as leads
UNION ALL
SELECT 'site2', 68099, 2342)
  
select *, 
findConfidenceIntervalFloor(clicks, leads, 0.005) as bot_interval_del,
findConfidenceIntervalCeil(clicks, leads, 0.005) as top_interval_del,
findConfidenceIntervalFloor(clicks, leads, 0.05) as bot_interval_add,
findConfidenceIntervalCeil(clicks, leads, 0.05) as top_interval_add
from t0
当我将其集成到查询第二个函数中以查找置信区间上限时,返回NaN。 我不明白为什么它在BigQuery中不起作用

CREATE TEMP FUNCTION findConfidenceIntervalFloor(C INT64, L INT64, p FLOAT64)
RETURNS FLOAT64
LANGUAGE js AS """
  function binomial_test(k, n, p){
    if(k < 0 || k > n || n <= 0 || p < 0 || p > 1) return NaN;
    // i = 0 term
    var logcoef = 0;
    var pvalue = Math.pow(Math.E, n*Math.log(1-p)); // Math.exp is not available
    // i > 0 terms
    for(var i = 1; i <= k; i++) {
      logcoef = logcoef + Math.log(n-i+1) - Math.log(i);
      pvalue = pvalue + Math.pow(Math.E, logcoef + i*Math.log(p) + (n-i)*Math.log(1-p));
    }
    return pvalue;
  }
  let CR = L/C
    let x1 = 0
    let x2 = L   
    while ((x2 - x1) > 1) {       
        let x = Math.ceil((x2 - x1) / 2 + x1)
        
        if (binomial_test(x, C, CR) < p/2) {
            x1 = x
        } else {
            x2 = x
        }
        
    }
    return x2;
  """;

CREATE TEMP FUNCTION findConfidenceIntervalCeil(C INT64, L INT64, p FLOAT64)
RETURNS FLOAT64
LANGUAGE js AS """
  function binomial_test(k, n, p){
    if(k < 0 || k > n || n <= 0 || p < 0 || p > 1) return NaN;
    var logcoef = 0;
    var pvalue = Math.pow(Math.E, n*Math.log(1-p)); 
    for(var i = 1; i <= k; i++) {
      logcoef = logcoef + Math.log(n-i+1) - Math.log(i);
      pvalue = pvalue + Math.pow(Math.E, logcoef + i*Math.log(p) + (n-i)*Math.log(1-p));
    }
    return pvalue;
  }
  let CR = L/C;
    let x1 = L;
    let x2 = C;  
    while ((x2 - x1) > 1) {       
        let x = Math.ceil((x2 - x1) / 2 + x1);
        
        if (binomial_test(x, C, CR) < (1 - p/2)) {
            x1 = x;
        } else {
            x2 = x;
        }        
    }
    return x1;
  """;
WITH t0 as (SELECT 'site1' as name, 97000 as clicks, 3784 as leads
UNION ALL
SELECT 'site2', 68099, 2342)
  
select *, 
findConfidenceIntervalFloor(clicks, leads, 0.005) as bot_interval_del,
findConfidenceIntervalCeil(clicks, leads, 0.005) as top_interval_del,
findConfidenceIntervalFloor(clicks, leads, 0.05) as bot_interval_add,
findConfidenceIntervalCeil(clicks, leads, 0.05) as top_interval_add
from t0
我认为您应该简单地修复函数的签名,以使用FLOAT64而不是INT64,如下所示

CREATE TEMP FUNCTION findConfidenceIntervalFloor(C FLOAT64, L FLOAT64, p FLOAT64)    

CREATE TEMP FUNCTION findConfidenceIntervalCeil(C FLOAT64, L FLOAT64, p FLOAT64)  
如果您这样做,您将得到输出

Row name    clicks  leads   bot_interval_del    top_interval_del    bot_interval_add    top_interval_add     
1   site1   97000   3784    3616.0              3953.0              3666.0              3902.0   
2   site2   68099   2342    2210.0              2476.0              2249.0              2435.0     
有关更多详细信息,请参阅