mirror of
https://github.com/Karaka-Management/phpOMS.git
synced 2026-02-11 22:38:42 +00:00
implement article affinity analysis
This commit is contained in:
parent
d556756283
commit
44d663d176
110
Business/Marketing/ArticleCorrelationAffinity.php
Normal file
110
Business/Marketing/ArticleCorrelationAffinity.php
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Orange Management
|
||||||
|
*
|
||||||
|
* PHP Version 7.4
|
||||||
|
*
|
||||||
|
* @package phpOMS\Business\Marketing
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace phpOMS\Business\Marketing;
|
||||||
|
|
||||||
|
use phpOMS\Math\Statistic\Correlation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marketing ArticleAffinity
|
||||||
|
*
|
||||||
|
* This class provided basic marketing metric calculations
|
||||||
|
*
|
||||||
|
* @package phpOMS\Business\Marketing
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
final class ArticleCorrelationAffinity
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Affinity between items
|
||||||
|
*
|
||||||
|
* @var array[]
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private array $affinity = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Item order behaviour (when are which items ordered)
|
||||||
|
*
|
||||||
|
* In tearms of the pearson correlation these are our random variables
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
private array $items = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
*
|
||||||
|
* @param array[] $orders Array of orders which contains as elements the items ordered in the respective order
|
||||||
|
* @param bool $considerQuantity NOT_IMPLEMENTED!!! Should the quantity be considered
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function __construct(array $orders, bool $considerQuantity = false)
|
||||||
|
{
|
||||||
|
// find all possible items
|
||||||
|
$possibleItems = [];
|
||||||
|
foreach ($orders as $items) {
|
||||||
|
foreach ($items as $item => $quantity) {
|
||||||
|
if (!\in_array($item, $possibleItems)) {
|
||||||
|
$possibleItems[] = $item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the random variables
|
||||||
|
foreach ($orders as $items) {
|
||||||
|
foreach ($possibleItems as $item) {
|
||||||
|
$this->items[$item][] = $items[$item];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create the affinity table
|
||||||
|
foreach ($possibleItems as $item1) {
|
||||||
|
foreach ($possibleItems as $item2) {
|
||||||
|
if ($item1 !== $item2 &&!isset($this->affinity[$item1][$item2]) && !isset($this->affinity[$item2][$item1])) {
|
||||||
|
$this->affinity[$item1][$item2] = Correlation::bravaisPersonCorrelationCoefficientPopulation($this->items[$item1], $this->items[$item2]);
|
||||||
|
$this->affinity[$item2][$item1] = $this->affinity[$item1][$item2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort correlations
|
||||||
|
foreach ($possibleItems as $item) {
|
||||||
|
\arsort($this->affinity[$item]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the affinity between items
|
||||||
|
*
|
||||||
|
* @param mixed $item Item to check for possible affinities
|
||||||
|
* @param int $resultSize How many top matches should be returned
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*
|
||||||
|
* @since 1.0.0
|
||||||
|
*/
|
||||||
|
public function getAffinity($item, int $resultSize = 0) : array
|
||||||
|
{
|
||||||
|
if (!isset($this->affinity[$item])) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $resultSize < 1 ? $this->affinity[$item] : \array_slice($this->affinity[$item], 0, $resultSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
71
tests/Business/Marketing/ArticleCorrelationAffinityTest.php
Normal file
71
tests/Business/Marketing/ArticleCorrelationAffinityTest.php
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Orange Management
|
||||||
|
*
|
||||||
|
* PHP Version 7.4
|
||||||
|
*
|
||||||
|
* @package tests
|
||||||
|
* @copyright Dennis Eichhorn
|
||||||
|
* @license OMS License 1.0
|
||||||
|
* @version 1.0.0
|
||||||
|
* @link https://orange-management.org
|
||||||
|
*/
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace phpOMS\tests\Business\Marketing;
|
||||||
|
|
||||||
|
use phpOMS\Business\Marketing\ArticleCorrelationAffinity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @testdox phpOMS\tests\Business\Marketing\ArticleCorrelationAffinityTest: Article affinity/correlation
|
||||||
|
*
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
class ArticleCorrelationAffinityTest extends \PHPUnit\Framework\TestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @testdox The highest affinities between articles purchased are calculated correctly
|
||||||
|
* @group framework
|
||||||
|
*/
|
||||||
|
public function testAffinity() : void
|
||||||
|
{
|
||||||
|
$orders = [
|
||||||
|
['A' => 1, 'B' => 1, 'C' => 0, 'D' => 0],
|
||||||
|
['A' => 0, 'B' => 1, 'C' => 0, 'D' => 0],
|
||||||
|
['A' => 1, 'B' => 1, 'C' => 0, 'D' => 0],
|
||||||
|
['A' => 1, 'B' => 0, 'C' => 0, 'D' => 1],
|
||||||
|
['A' => 0, 'B' => 0, 'C' => 0, 'D' => 0],
|
||||||
|
['A' => 1, 'B' => 1, 'C' => 0, 'D' => 0],
|
||||||
|
['A' => 1, 'B' => 0, 'C' => 1, 'D' => 0],
|
||||||
|
['A' => 0, 'B' => 0, 'C' => 1, 'D' => 0],
|
||||||
|
['A' => 1, 'B' => 1, 'C' => 0, 'D' => 0],
|
||||||
|
['A' => 1, 'B' => 1, 'C' => 0, 'D' => 0],
|
||||||
|
['A' => 0, 'B' => 1, 'C' => 0, 'D' => 0],
|
||||||
|
['A' => 0, 'B' => 1, 'C' => 0, 'D' => 0],
|
||||||
|
['A' => 1, 'B' => 1, 'C' => 0, 'D' => 0],
|
||||||
|
['A' => 0, 'B' => 0, 'C' => 0, 'D' => 0],
|
||||||
|
['A' => 0, 'B' => 0, 'C' => 0, 'D' => 0],
|
||||||
|
];
|
||||||
|
|
||||||
|
$aff = new ArticleCorrelationAffinity($orders);
|
||||||
|
|
||||||
|
self::assertEqualsWithDelta(
|
||||||
|
[
|
||||||
|
'A' => 0.3273,
|
||||||
|
'C' => -0.4803,
|
||||||
|
'D' => -0.3273,
|
||||||
|
],
|
||||||
|
$aff->getAffinity('B'),
|
||||||
|
0.001
|
||||||
|
);
|
||||||
|
|
||||||
|
self::assertEqualsWithDelta(
|
||||||
|
[
|
||||||
|
'A' => 0.3273,
|
||||||
|
'D' => -0.3273,
|
||||||
|
],
|
||||||
|
$aff->getAffinity('B', 2),
|
||||||
|
0.001
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user