统计

本用户指南部分涵盖了数学表达式中可用的核心统计函数。

描述性统计

describe 函数返回数字数组的描述性统计。describe 函数返回一个包含描述性统计的名称/值对的单 元组

下面是一个简单示例,它从 logs 集合中选择文档的随机样本,对结果集中 response_d 字段进行矢量化,并使用 describe 函数返回有关该向量的描述性统计。

let(a=random(logs, q="*:*", fl="response_d", rows="50000"),
    b=col(a, response_d),
    c=describe(b))

当此表达式发送到 /stream 处理程序时,它会响应

{
  "result-set": {
    "docs": [
      {
        "sumsq": 36674200601.78738,
        "max": 1068.854686837548,
        "var": 1957.9752647562789,
        "geometricMean": 854.1445499569674,
        "sum": 42764648.83319176,
        "kurtosis": 0.013189848821424377,
        "N": 50000,
        "min": 656.023249311864,
        "mean": 855.2929766638425,
        "popVar": 1957.936105250984,
        "skewness": 0.0014560741802307174,
        "stdev": 44.24901428005237
      },
      {
        "EOF": true,
        "RESPONSE_TIME": 430
      }
    ]
  }
}

请注意,随机样本包含 50,000 条记录,响应时间仅为 430 毫秒。此大小的样本可用于可靠地估计非常大的基础数据集的统计数据,性能低于一秒。

describe 函数还可以在 Zeppelin-Solr 中以表格形式可视化

describe

直方图和频率表

直方图和频率表是用于可视化随机变量分布的工具。

hist 函数创建专为连续数据使用而设计的直方图。freqTable 函数创建频率表以用于离散数据。

直方图

在下面的示例中,直方图用于可视化来自 logs 集合的响应时间的随机样本。该示例使用 random 函数检索随机样本,并从结果集中的 response_d 字段创建向量。然后将 hist 函数应用于向量,以返回包含 22 个箱的直方图。hist 函数返回一个元组列表,其中包含每个箱的汇总统计信息。

let(a=random(logs, q="*:*", fl="response_d", rows="50000"),
    b=col(a, response_d),
    c=hist(b,  22))

当此表达式发送到 /stream 处理程序时,它会响应

{
  "result-set": {
    "docs": [
      {
        "prob": 0.00004896007228311655,
        "min": 675.573084576817,
        "max": 688.3309631697003,
        "mean": 683.805542728906,
        "var": 50.9974629924082,
        "cumProb": 0.000030022417162809913,
        "sum": 2051.416628186718,
        "stdev": 7.141250800273591,
        "N": 3
      },
      {
        "prob": 0.00029607514624062624,
        "min": 696.2875238591652,
        "max": 707.9706315779541,
        "mean": 702.1110569558929,
        "var": 14.136444379466969,
        "cumProb": 0.00022705264963879807,
        "sum": 11233.776911294284,
        "stdev": 3.759846323916307,
        "N": 16
      },
      {
        "prob": 0.0011491235433157194,
        "min": 709.1574910598678,
        "max": 724.9027194369135,
        "mean": 717.8554290699951,
        "var": 20.6935845290122,
        "cumProb": 0.0009858515418689757,
        "sum": 41635.61488605971,
        "stdev": 4.549020172412098,
        "N": 58
      },
      ...
      ]}}

使用 Zeppelin-Solr,可以先将直方图可视化为表格

histtable

然后,可以通过在 x 轴 上绘制箱的 均值,在 y 轴 上绘制 prob(概率)来使用面积图可视化直方图

hist

可以通过将 y 轴 切换到 cumProb 列来绘制累积概率

cumProb

自定义直方图

可以通过将多个 stats 函数的输出合并到一个直方图中来定义和可视化自定义直方图。自定义直方图允许基于查询比较箱,而不是自动对数字字段进行分箱。

stats 函数首先在用户指南的搜索、抽样和聚合部分中进行了讨论。

一个简单的示例将说明如何定义和可视化自定义直方图。

在此示例中,三个 stats 函数被包装在一个 plist 函数中。plist(并行列表)函数并行执行其每个内部函数,并将结果串联到单个流中。plist 还维护每个子函数的输出顺序。在此示例中,每个 stats 函数计算与特定查询匹配的文档数。在这种情况下,它们计算包含术语铜、金和银的文档数。然后将包含计数的元组列表存储在变量 a 中。

然后创建一个标签数组并将其设置为变量 l

最后,zplot 函数用于绘制标签向量和 count(*) 列。请注意,col 函数在 zplot 函数中用于从 stats 结果中提取计数。

custom hist

频率表

freqTable 函数为离散数据集返回频率分布。freqTable 函数不会像直方图那样创建箱。相反,它计算每个离散数据值的出现次数,并返回一个元组列表,其中包含每个值的频率统计信息。

下面是一个频率表的示例,该频率表基于股票代码 amzn 的每日开盘价的舍入差值结果集构建。

此示例很有趣,因为它显示了一个到达结果的多步骤过程。第一步是使用股票代码 amznstocks 集合中搜索记录。请注意,结果集按日期升序排列,并返回 open_d 字段,该字段是当天的开盘价。

然后将 open_d 字段矢量化并设置为变量 b,其中现在包含按日期升序排列的开盘价向量。

然后使用 diff 函数计算开盘价向量的一阶差分。一阶差分只是从数组中的每个值中减去前一个值。这将提供每天的价格差数组,其中将显示开盘价的每日变化。

然后使用 round 函数将价格差四舍五入到最接近的整数,以创建一个离散值向量。此示例中的 round 函数实际上是在整数边界处对连续数据进行分箱

最后,在离散值上运行 freqTable 函数以计算频率表。

let(a=search(stocks,
             q="ticker_s:amzn",
             fl="open_d, date_dt",
             sort="date_dt asc",
             rows=25000),
    b=col(a, open_d),
    c=diff(b),
    d=round(c),
    e=freqTable(d))

当此表达式发送到 /stream 处理程序时,它会响应

 {
   "result-set": {
     "docs": [
       {
         "pct": 0.00019409937888198756,
         "count": 1,
         "cumFreq": 1,
         "cumPct": 0.00019409937888198756,
         "value": -57
       },
       {
         "pct": 0.00019409937888198756,
         "count": 1,
         "cumFreq": 2,
         "cumPct": 0.00038819875776397513,
         "value": -51
       },
       {
         "pct": 0.00019409937888198756,
         "count": 1,
         "cumFreq": 3,
         "cumPct": 0.0005822981366459627,
         "value": -49
       },
       ...
       ]}}

使用 Zeppelin-Solr,频率表可以首先可视化为表格

freqTable

然后,可以通过切换到散点图并为x 轴选择value列,为y 轴选择count列来绘制频率表

freqTable1

请注意,该可视化很好地显示了股票价格每日变化的频率,该频率已四舍五入为整数。出现频率最高的值为 0,出现次数为 1494,其次是 -1 和 1,出现次数约为 700。

百分位数

percentile 函数返回样本集中特定百分位数的估计值。以下示例返回一个随机样本,其中包含日志集合中的response_d字段。response_d字段被矢量化,并为该矢量计算第 20 个百分位数

let(a=random(logs, q="*:*", rows="15000", fl="response_d"),
    b=col(a, response_d),
    c=percentile(b, 20))

当此表达式发送到 /stream 处理程序时,它会响应

 {
   "result-set": {
     "docs": [
       {
         "c": 818.073554
       },
       {
         "EOF": true,
         "RESPONSE_TIME": 286
       }
     ]
   }
 }

percentile 函数还可以计算百分位数值的数组。以下示例正在计算response_d字段的随机样本的第 20、40、60 和 80 个百分位数

let(a=random(logs, q="*:*", rows="15000", fl="response_d"),
    b=col(a, response_d),
    c=percentile(b, array(20,40,60,80)))

当此表达式发送到 /stream 处理程序时,它会响应

{
  "result-set": {
    "docs": [
      {
        "c": [
          818.0835543394625,
          843.5590348165282,
          866.1789509894824,
          892.5033386599067
        ]
      },
      {
        "EOF": true,
        "RESPONSE_TIME": 291
      }
    ]
  }
}

分位数图

分位数图或 QQ 图是用于直观比较两个或更多分布的强大工具。

分位数图在同一可视化中绘制来自两个或更多分布的分位数。这允许在每个百分位数处直观比较分布。一个简单的示例将有助于说明分位数图的强大功能。

在此示例中,两个股票代码googamzn的每日股票价格变化分布使用分位数图可视化。

该示例首先创建一个表示将计算的分位数的值数组,并将此数组设置为变量p。然后,为代码amzngoog绘制change_d字段的随机样本。change_d字段表示一天内的股票价格变化。然后,change_d字段对于两个样本都被矢量化,并放入变量amzngoog中。然后使用percentile函数计算两个向量的百分位数。请注意,变量p用于指定计算的分位数列表。

最后,zplot用于在x 轴上绘制百分位数序列,并在y 轴上绘制两个分布的计算百分位数值。并且使用折线图来可视化 QQ 图。

quantile plot

此分位数图清晰地展示了amzngoogl的每日价格变化分布。在该图中,x 轴是百分位数,y 轴是计算的百分位数值。

请注意,goog百分位数值从低于amzn图开始,结束时高于amzn图,并且斜率更陡。这显示了goog价格变化分布中更大的可变性。该图清晰地展示了整个百分位数范围内的分布差异。

相关性和协方差

相关性和协方差衡量随机变量如何一起波动。

相关性和相关矩阵

相关性是两个向量之间线性相关性的度量。相关性在 -1 和 1 之间缩放。

支持三种相关类型

  • pearsons(默认)

  • kendalls

  • spearmans

通过在函数调用中添加type命名参数来指定相关类型。

在下面的示例中,使用random函数从日志集合中提取包含两个字段(filesize_dresponse_d)的随机样本。这些字段被矢量化到变量xy中,然后使用corr函数计算两个向量的Spearman相关性。

correlation

相关矩阵

相关矩阵是用于可视化两个或多个向量之间相关性的强大工具。

如果将矩阵作为参数传递,则corr函数将构建相关矩阵。通过关联矩阵的来计算相关矩阵。

以下示例演示了相关矩阵与 2 维分面的强大组合。

在此示例中,facet2D函数用于对nyc311投诉数据库中的字段complaint_type_szip_s生成二维分面聚合。聚合了排名前 20的投诉类型和每种投诉类型的排名前 25的邮政编码。结果是一系列元组,每个元组都包含字段complaint_type_szip_s和该对的计数。

然后使用pivot函数将字段转换为矩阵,其中zip_s字段作为complaint_type_s字段作为count(*)字段填充矩阵单元格中的值。

然后使用corr函数关联矩阵的。这会生成一个相关矩阵,该矩阵显示投诉类型如何根据其出现的邮政编码相关联。另一种看待它的方式是,它显示了不同的投诉类型如何倾向于在邮政编码中同时出现。

最后,使用zplot函数将相关矩阵绘制为热图。

corrmatrix

请注意,在示例中,相关矩阵是正方形,投诉类型显示在x轴和 y 轴上。热图中单元格的颜色显示了投诉类型之间相关性的强度。

热图是交互式的,因此将鼠标悬停在其中一个单元格上会弹出该单元格的值。

corrmatrix2

请注意,热/热水和不卫生状况投诉的相关性为 8(四舍五入到最接近的十分之一)。

协方差和协方差矩阵

协方差是相关性的非缩放度量。

cov 函数计算两个数据向量的协方差。

在下面的示例中,使用 random 函数从日志集合中抽取包含两个字段(filesize_dresponse_d)的随机样本。将字段矢量化到变量 xy 中,然后使用 cov 函数计算两个向量的协方差。

covariance

如果将矩阵传递给 cov 函数,它将自动计算矩阵的的协方差矩阵。

请注意,在下面的示例中,xy 向量被添加到矩阵中。然后对矩阵进行转置,将行转换为列,并计算矩阵列的协方差矩阵。

let(a=random(logs, q="*:*", fl="filesize_d, response_d", rows=50000),
    x=col(a, filesize_d),
    y=col(a, response_d),
    m=transpose(matrix(x, y)),
    covariance=cov(m))

当此表达式发送到 /stream 处理程序时,它会响应

 {
   "result-set": {
     "docs": [
       {
         "covariance": [
           [
             4018404.072532102,
             80243.3948172242
           ],
           [
             80243.3948172242,
             1948.3216661122592
           ]
         ]
       },
       {
         "EOF": true,
         "RESPONSE_TIME": 534
       }
     ]
   }
 }

协方差矩阵包含两个向量的方差和向量之间的协方差,格式如下

         x                 y
 x [4018404.072532102, 80243.3948172242],
 y [80243.3948172242,  1948.3216661122592]

协方差矩阵始终为方阵。因此,由 3 个向量创建的协方差矩阵将生成一个 3 x 3 矩阵。

统计推断测试

统计推断测试对随机样本进行假设检验,并返回 p 值,可用于推断整个总体测试的可靠性。

提供以下统计推断测试

  • anova:单因素方差分析测试两个或多个随机样本的均值是否存在统计学上的显著差异。

  • ttest:T 检验测试两个随机样本的均值是否存在统计学上的显著差异。

  • pairedTtest:配对 t 检验测试具有配对数据的两个随机样本的均值是否存在统计学上的显著差异。

  • gTestDataSet:G 检验测试两个离散数据样本是否来自同一总体。

  • chiSquareDataset:卡方检验测试两个离散数据样本是否来自同一总体。

  • mannWhitney:曼-惠特尼检验是一种非参数检验,用于测试两个连续数据样本是否来自同一总体。当不满足 T 检验的基本假设时,通常使用曼-惠特尼检验代替 T 检验。

  • ks:Kolmogorov-Smirnov 检验测试两个连续数据样本是否来自同一分布。

下面是一个 T 检验的简单示例,该检验对两个随机样本执行。返回的 p 值为 .93,这意味着我们可以接受零假设,即两个样本在均值上没有统计学上的显着差异。

let(a=random(collection1, q="*:*", rows="1500", fl="price_f"),
    b=random(collection1, q="*:*", rows="1500", fl="price_f"),
    c=col(a, price_f),
    d=col(b, price_f),
    e=ttest(c, d))

当此表达式发送到 /stream 处理程序时,它会响应

{
  "result-set": {
    "docs": [
      {
        "e": {
          "p-value": 0.9350135639249795,
          "t-statistic": 0.081545541074817
        }
      },
      {
        "EOF": true,
        "RESPONSE_TIME": 48
      }
    ]
  }
}

转换

在统计分析中,在执行统计计算之前转换数据集通常很有用。统计函数库包括以下常用转换

  • rank:返回一个数字数组,其中包含原始数组中每个元素的秩转换值。

  • log:返回一个数字数组,其中包含原始数组中每个元素的自然对数。

  • log10:返回一个数字数组,其中包含原始数组中每个元素的以 10 为底的对数。

  • sqrt:返回一个数字数组,其中包含原始数组中每个元素的平方根。

  • cbrt:返回一个数字数组,其中包含原始数组中每个元素的立方根。

  • recip:返回一个数字数组,其中包含原始数组中每个元素的倒数。

下面是一个对对数转换数据集执行 t 检验的示例

let(a=random(collection1, q="*:*", rows="1500", fl="price_f"),
    b=random(collection1, q="*:*", rows="1500", fl="price_f"),
    c=log(col(a, price_f)),
    d=log(col(b, price_f)),
    e=ttest(c, d))

当此表达式发送到 /stream 处理程序时,它会响应

{
  "result-set": {
    "docs": [
      {
        "e": {
          "p-value": 0.9655110070265056,
          "t-statistic": -0.04324265449471238
        }
      },
      {
        "EOF": true,
        "RESPONSE_TIME": 58
      }
    ]
  }
}

反转换

使用 loglog10sqrtcbrt 函数转换的向量可以使用 pow 函数进行反转换。

下面的示例显示了如何对已通过 sqrt 函数转换的数据进行反转换。

let(echo="b,c",
    a=array(100, 200, 300),
    b=sqrt(a),
    c=pow(b, 2))

当此表达式发送到 /stream 处理程序时,它会响应

{
  "result-set": {
    "docs": [
      {
        "b": [
          10,
          14.142135623730951,
          17.320508075688775
        ],
        "c": [
          100,
          200.00000000000003,
          300.00000000000006
        ]
      },
      {
        "EOF": true,
        "RESPONSE_TIME": 0
      }
    ]
  }
}

下面的示例显示了如何对已通过 log10 函数转换的数据进行反转换。

let(echo="b,c",
    a=array(100, 200, 300),
    b=log10(a),
    c=pow(10, b))

当此表达式发送到 /stream 处理程序时,它会响应

{
  "result-set": {
    "docs": [
      {
        "b": [
          2,
          2.3010299956639813,
          2.4771212547196626
        ],
        "c": [
          100,
          200.00000000000003,
          300.0000000000001
        ]
      },
      {
        "EOF": true,
        "RESPONSE_TIME": 0
      }
    ]
  }
}

使用 recip 函数转换的向量可以通过取倒数的倒数来进行反转换。

下面的示例显示了 recip 函数的反转换示例。

let(echo="b,c",
    a=array(100, 200, 300),
    b=recip(a),
    c=recip(b))

当此表达式发送到 /stream 处理程序时,它会响应

{
  "result-set": {
    "docs": [
      {
        "b": [
          0.01,
          0.005,
          0.0033333333333333335
        ],
        "c": [
          100,
          200,
          300
        ]
      },
      {
        "EOF": true,
        "RESPONSE_TIME": 0
      }
    ]
  }
}

Z 分数

zscores 函数将数字数组转换为 Z 分数数组。Z 分数是一个数字与均值的标准差数。

下面的示例计算数组中值的 Z 分数。

let(a=array(1,2,3),
    b=zscores(a))

当此表达式发送到 /stream 处理程序时,它会响应

{
  "result-set": {
    "docs": [
      {
        "b": [
          -1,
          0,
          1
        ]
      },
      {
        "EOF": true,
        "RESPONSE_TIME": 27
      }
    ]
  }
}