Passed
Pull Request — master (#232)
by Arkadiusz
02:37
created

SelectKBest::scores()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 8
c 0
b 0
f 0
rs 9.4285
cc 2
eloc 4
nc 2
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Phpml\FeatureSelection;
6
7
use Phpml\Exception\InvalidArgumentException;
8
use Phpml\Exception\InvalidOperationException;
9
use Phpml\FeatureSelection\ScoringFunction\ANOVAFValue;
10
use Phpml\Transformer;
11
12
final class SelectKBest implements Transformer
13
{
14
    /**
15
     * @var ScoringFunction
16
     */
17
    private $scoringFunction;
18
19
    /**
20
     * @var int
21
     */
22
    private $k;
23
24
    /**
25
     * @var array|null
26
     */
27
    private $scores = null;
28
29
    /**
30
     * @var array|null
31
     */
32
    private $keepColumns = null;
33
34
    public function __construct(?ScoringFunction $scoringFunction = null, int $k = 10)
35
    {
36
        if ($scoringFunction === null) {
37
            $scoringFunction = new ANOVAFValue();
38
        }
39
40
        $this->scoringFunction = $scoringFunction;
41
        $this->k = $k;
42
    }
43
44
    public function fit(array $samples, ?array $targets = null): void
45
    {
46
        if ($targets === null || empty($targets)) {
47
            throw InvalidArgumentException::arrayCantBeEmpty();
48
        }
49
50
        $this->scores = $sorted = $this->scoringFunction->score($samples, $targets);
51
        if ($this->k >= count($sorted)) {
52
            return;
53
        }
54
55
        arsort($sorted);
56
        $this->keepColumns = array_slice($sorted, 0, $this->k, true);
57
    }
58
59
    public function transform(array &$samples): void
60
    {
61
        if ($this->keepColumns === null) {
62
            return;
63
        }
64
65
        foreach ($samples as &$sample) {
66
            $sample = array_values(array_intersect_key($sample, $this->keepColumns));
67
        }
68
    }
69
70
    public function scores(): array
71
    {
72
        if ($this->scores === null) {
73
            throw new InvalidOperationException('SelectKBest require to fit first to get scores');
74
        }
75
76
        return $this->scores;
77
    }
78
}
79