Adnan
Adnan

Reputation: 26350

How to define trends according to some values?

I am trying to to mark some trends, so I have 1 as the lowest and 5 as the biggest value.

So for example,

I may have the following case:

5,4,5,5   (UP)
3,4,      (UP)
4,3,3     (DOWN)
4,4,4,4,  (FLAT - this is OK for all same numbers)

I am planning to have unlimited number of ordered values as input, an as an output I will just show an (UP), (DOWN), or (FLAT) image.

Any ideas on how I can achieve this?

Sorry if I am not descriptive enough.

Thank you all for you time.

Upvotes: 3

Views: 2849

Answers (6)

paj
paj

Reputation: 1187

I used the code from @liquorvicar to determine Google search page rank trends, but added some extra trend values to make it more accurate:

nochange - no change

better (higher google position = lower number)

worse (lower google position = higher number)

I also added extra checks when the last value had no change, but taking in account the previous changes i.e.

worsenochange (no change, previouse was worse - lower number)

betternochange (no change, previouse was better - lower number)

I used these values to display a range of trend icons:

$_trendIndicator="<img title="trend" width="16" src="/include/main/images/trend-'. $this->getTrend($_positions). '-icon.png">";

example of trend icons

    private function getTrend($_positions)
{
    // calculate trend based on last value
    //
    $_previousValue = false;
    $_trend = 'nochange';

    foreach( $_positions as $_currentValue ) {

        if( $_previousValue !== false ) {

            if( $_currentValue > $_previousValue ) {
                $_trend = 'better';
            } elseif( $_currentValue < $_previousValue ) {
                $_trend = 'worse';
            }

            if ($_trend==='worse' && ($_previousValue == $_currentValue)) {$_trend = 'worsenochange';}

            if ($_trend==='better' && ($_previousValue == $_currentValue)) {$_trend = 'betternochange';}
        }

        $_previousValue = $_currentValue;
    } 

    return $_trend;
}

Upvotes: 0

Mark Baker
Mark Baker

Reputation: 212452

Use least square fit to calculate the "slope" of the values.

function leastSquareFit(array $values) {
    $x_sum = array_sum(array_keys($values));
    $y_sum = array_sum($values);
    $meanX = $x_sum / count($values);
    $meanY = $y_sum / count($values);
    // calculate sums
    $mBase = $mDivisor = 0.0;
    foreach($values as $i => $value) {
        $mBase += ($i - $meanX) * ($value - $meanY);
        $mDivisor += ($i - $meanX) * ($i - $meanX);
    }

    // calculate slope
    $slope = $mBase / $mDivisor;
    return $slope;
}   //  function leastSquareFit()

$trend = leastSquareFit(array(5,4,5,5));

(Untested)

If the slope is positive, the trend is upwards; if negative, it's downwards. Use your own judgement to decide what margin (positive or negative) is considered flat.

Upvotes: 6

matino
matino

Reputation: 17725

echo foo(array(5,4,5,5)); // UP
echo foo(array(3,4)); // UP
echo foo(array(4,3,3)); // DOWN
echo foo(array(4,4,4,4)); // FLAT

function foo($seq)
{
    if (count(array_unique($seq)) === 1)
        return 'FLAT';

    $trend = NULL;
    $count = count($seq);
    $prev = $seq[0];
    for ($i = 1; $i < $count; $i++)
    {
        if ($prev < $seq[$i])
        {
            $trend = 'UP';
        }
        if ($prev > $seq[$i])
        {
            $trend = 'DOWN';
        }
        $prev = $seq[$i];
    }

    return $trend;
}

Upvotes: 0

liquorvicar
liquorvicar

Reputation: 6106

A little bit hard to answer based on the limited info you provide, but assuming that:

  • if there's no movement at all the trend is FLAT,
  • otherwise, the trend is the last direction of movement,

then this code should work:

$input = array();

$previousValue = false;
$trend = 'FLAT';

foreach( $input as $currentValue ) {
    if( $previousValue !== false ) {
        if( $currentValue > $previousValue ) {
            $trend = 'UP';
        } elseif( $currentValue < $previousValue ) {
            $trend = 'DOWN';
        }
    }
    $previousValue = $currentValue;
} 

Upvotes: 2

user980124
user980124

Reputation: 9

I'm not sure if i understand your problem totally but I would put the values in an array and use a code like this (written in pseudocode):

    int i = 0;
    String trend = "FLAT":
    while(i<length(array)) {
       if(array(i)<array(i+1)) {
          trend = "UP";
       }
       else if(array(i)>array(i+1) {
          trend = "DOWN";
       }
       i++;
    }

EDIT: this would obviously only display the trend of the latest alteration one would also may count the number of times the trend is up or down and determine the overall trend by that values

Upvotes: 0

DhruvPathak
DhruvPathak

Reputation: 43245

For your examples :

  • Calculate longest increasing subsequence, A
  • Calulate longest decreasing subsequence , B

Going by your logic, if length of A is larger than B , its an UP , else DOWN. You will also need to keep track of all equals using one boolean variable to mark FLAT trend.

Query : What trend would be :

3,4,5,4,3 ?
3,4,4,4,3 ?
1,2,3,4,4,3,2,2,1 ?

Then the logic might need some alterations depending upon what your requirements are .

Upvotes: 0

Related Questions