xp-forge/pivot

数据透视表

v3.2.0 2024-03-24 13:11 UTC

This package is auto-updated.

Last update: 2024-08-24 14:09:01 UTC


README

Build status on GitHub XP Framework Module BSD Licence Requires PHP 7.0+ Supports PHP 8.0+ Latest Stable Version

与数据透视表一起工作 pivot tables

示例

给定以下输入,例如来自日志文件

2015-05-10 00:00:09 OK: 304 100 bytes
2015-05-10 00:00:48 GOOD: 200 102 bytes (ETag: 214ceb4b-980-3a7bbd9630480)
2015-05-10 03:00:49 ERROR: 404 512 bytes (Not found)
2015-05-11 00:00:17 OK: 304 102 bytes
2015-05-11 02:01:01 ERROR: 500 0 bytes (Internal Server Error)
2015-05-11 02:01:02 ERROR: 500 256 bytes (Internal Server Error)
...

我们将使用 sscanf() 进行解析,将行转换为以下数组

["2015-05-10", "00:00:48", "GOOD", 200, 95, "ETag: 214ceb4b-980-3a7bbd9630480"]

然后我们可以使用数组偏移量将其加载到我们的数据透视表中(如果我们有一个映射,我们可以使用其字符串键;对于对象,我们将传递获取器引用;对于更复杂的情况,我们可以传递闭包)。组合起来,我们得到以下结果

use io\streams\{TextReader, FileInputStream};
use util\data\PivotCreation;

$pivot= (new PivotCreation())
  ->groupingBy(2)        // category
  ->groupingBy(3)        // code
  ->spreadingBy(0)       // date
  ->summing(4, 'bytes')  // bytes
  ->create()
);

$reader= new TextReader(new FileInputStream('measures.log'));
while (null !== ($line= $reader->readLine())) {
  $pivot->add(sscanf($line, '%[0-9-] %[0-9:] %[^:]: %d %d bytes (%[^)])'));
}

结果表格看起来可能像这样(使用 "b:" 作为 字节 的缩写 - 这在我们在多列上进行求和时变得相关)。

.------------------------------------------------------- ~ ---------------------------.
|                    || Columns                             |                         |
|                    ||--------------------------------- ~ -|                         |
| Category  | Count  || 2015-05-10    | 2015-05-11    |- ~ -| Sum        | Average    |
|-----------|--------||---------------|---------------|- ~ -|------------|------------|
| OK        | 2      || 1, b:100      | 1, b:102      |- ~ -| b:202      | b:101      |
| GOOD      | 1      || 1, b:102      |               |- ~ -| b:102      | b:102      |
| ERROR     | 3      || 2, b:512      | 1, b:256      |- ~ -| b:768      | b:256      |
| ^- client | ^- 1   || ^- 1, b:512   |               |- ~ -| ^- b:512   | ^- b:512   |
|   ^- 404  |   ^- 1 ||   ^- 1, b:512 |               |- ~ -|   ^- b:512 |   ^- b:512 |
| ^- server | ^- 2   || ^- 1, b:0     | ^- 1, b:256   |- ~ -| ^- b:256   | ^- b:128   |
|   ^- 500  |   ^- 2 ||   ^- 1, b:0   |   ^- 1, b:256 |- ~ -|   ^- b:256 |  ^- b:128  |
|-----------|--------||---------------|---------------|- ~ -|------------|------------|
| Total     | 6      || b:714         | b:358         |- ~ -| b:1072     | b:178.7    |
`------------------------------------------------------- ~ ---------------------------´

访问数据透视表中的值

可以通过 count() 方法检索按分组列分组的记录数。可以通过将类别传递到相应的方法来访问聚合。

$count= $pivot->count('OK');                                // 2
$count= $pivot->count();                                    // 6

$count= $pivot->records('2015-05-10', 'OK');                // 1
$count= $pivot->records('2015-05-10');                      // 4

$transferred= $pivot->column('2015-05-10', 'OK')['bytes'];  // 100
$transferred= $pivot->column('2015-05-10')['bytes'];        // 714

$transferred= $pivot->sum('OK')['bytes'];                   // 202
$transferred= $pivot->sum()['bytes'];                       // 1072

$average= $pivot->average('OK')['bytes'];                   // 101.0
$average= $pivot->average()['bytes'];                       // 178.7

深入分析

我们可以通过使用 rows() 方法根据我们分组的类别进行深入分析。为了计算类别在总百分比中的分布,我们将使用 count() 方法。

$rows= $pivot->rows();                         // ['OK', 'GOOD', 'ERROR']

// OK: 2 / 6 = 33.3%
// GOOD: 1 / 6 = 16.7%
// ERROR: 3 / 6 = 50.0%
$total= $pivot->count();
foreach ($rows as $cat) {
  $count= $pivot->count($cat);
  printf("%s: %d / %d = %.1f%%\n", $cat, $count, $total, $count / $total * 100);
}

// client: 1
// server: 2
foreach ($pivot->rows('ERROR') as $code) {
  printf("ERROR %s: %dx\n", $row, $pivot->count('ERROR', $code));
}

也有兴趣看到随时间的发展,所以我们将基于列进行深入分析。

$columns= $pivot->columns();                   // ['2015-05-10', '2015-05-11']

// 2015-05-10: 714 / 1072 bytes = 66.6%
// 2015-05-11: 358 / 1072 bytes = 33.4%
$total= $pivot->total()['bytes'];
foreach ($columns as $date) {
  $bytes= $pivot->column($date)['bytes'];
  printf("%s: %d / %d bytes = %.1f%%\n", $date, $bytes, $total, $bytes / $total * 100);
}