xp-forge / pivot
数据透视表
v3.2.0
2024-03-24 13:11 UTC
Requires
- php: >=7.0.0
- xp-forge/sequence: ^10.0 | ^9.0 | ^8.0 | ^7.0 | ^6.0 | ^5.0
- xp-framework/core: ^12.0 | ^11.0 | ^10.0 | ^9.0 | ^8.0 | ^7.0
Requires (Dev)
- xp-framework/test: ^2.0 | ^1.0
README
与数据透视表一起工作 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); }