3

Is there any easy way to find out what's the trend of the list?

For example:

  • [5.0, 6.0, 9.0, 4.0, 10.0]. On the whole, its elements are increasing over time.
  • [6.0, 4.0, 5.0, 4.0, 3.0]. Its elements are decreasing over time.

Ideally, I want a Boolean result from these kinds of lists.

Actually, I'd like to know the trend of a collection of data. not linear increasing or exactly increasing one by one. In the real world, some data not always good, Perhaps there are one or two quarters of data not as good as it used to be(but not too bad, also not too much), but as long as Its trend is good, It is good.

jpp
  • 159,742
  • 34
  • 281
  • 339
Frank Wang
  • 41
  • 1
  • 5
  • Bool stating what exactly ? 'True' for increasing and 'False' for decreasing ? – Kanmani Mar 19 '18 at 09:26
  • do you mean that you want to check whether the values are increasing or decreasing? – Alireza Mar 19 '18 at 09:28
  • Before you can attempt to solve the coding part of your problem, you should decide what kind of [regression analysis](https://en.wikipedia.org/wiki/Regression_analysis) you want to determine a trend. In the real world, many data sets will get better and worse all the time. Or do you want a tri-state output of `always improving`, `always decaying`, `no clear trend`? – phihag Mar 19 '18 at 09:31

3 Answers3

11

On the whole, Its elements are increasing.

I take this to mean you want to consider the change in moving average. Half the job is defining what you really want, so I advise you think carefully about this before starting to write logic.

I've combined a moving average solution by @Jaime with np.diff to suggest a possible way to infer what you want.

import numpy as np

def moving_average(a, n=3) :
    ret = np.cumsum(a, dtype=float)
    ret[n:] = ret[n:] - ret[:-n]
    return ret[n - 1:] / n

lst1 = [5.0, 6.0, 9.0, 4.0, 10.0]
lst2 = [6.0, 4.0, 5.0, 4.0, 3.0]

res1 = np.all(np.diff(moving_average(np.array(lst1), n=4))>0)
# True; i.e. "generally increasing"

res2 = np.all(np.diff(moving_average(np.array(lst2), n=4))>0)
# False, i.e. "generally not increasing"

Explanation

  • moving_average calculates the moving average across a window of 4 entries.
  • In each case you get an array of 2 numbers (for list of length 5).
  • np.diff then calculates the pairwise changes between these numbers.
  • np.all with test >0 determines if the changes are all positive or not all positive. An oversimplification driven by no clear requirement.
jpp
  • 159,742
  • 34
  • 281
  • 339
  • Just so I understand, what this does is taking each difference between consecutive numbers, sum the negative ones, sum the positive ones, and if the difference between the two sums is positive, then the trend is increasing. Is that correct? – ChatterOne Mar 19 '18 at 09:44
  • @ChatterOne, I've added an explanation. – jpp Mar 19 '18 at 09:47
  • @FrankWang, Really what you need is a *precise mathematical equation* of what you want to achieve. A description is great, but in itself is not conducive to code translation. – jpp Mar 20 '18 at 09:14
  • 2
    This is a solid answer given the ambiguity of the request and the elegance of the answer. – deepelement Apr 06 '19 at 02:02
0

You can simply check , Will this work ?

def checker(list_):
    check={}
    temp = []
    for m, n in enumerate(list_):
        try:
            if list_[m] < list_[m + 1]:
                temp.append('Increasing')
            else:
                temp.append('Decreasing')
        except IndexError:
            pass
    check[temp.count('Increasing')] = 1
    check[temp.count('Decreasing')] = 0


    return check[max(check)]

test_Case 1:

print(checker([5.0, 6.0, 9.0, 4.0, 10.0]))

output:

1

test_Case 2

print(checker([6.0, 4.0, 5.0, 4.0, 3.0]))

output:

0
Aaditya Ura
  • 12,007
  • 7
  • 50
  • 88
  • 1
    This will only check how many of those are going up and how many are going down. If you have many tiny drops, let's say 10 drops of -1, and one big increase, let's say an increase of +1000, I think that should be marked as increasing, or am I missing something? – ChatterOne Mar 19 '18 at 13:29
  • @ChatterOne yes you are missing something , so if i give print(checker([-1,-1,-1,-1,-1,-1,-1,10000])) it will return 0 which is decreasing. – Aaditya Ura Mar 19 '18 at 14:28
  • yes, that's my point, I think that's incorrect and it should be marked as increasing, because as a whole the series is going up. But I think that the definition of "increasing" might vary maybe. – ChatterOne Mar 19 '18 at 15:53
0

I just had the same issue, and created a version using only pandas for this problem, making the implementation of the moving_average function unnecessary.

def get_trend(array=[], reverse=False):
    array  = pd.Series(array).iloc[::-1].reset_index(drop=True) if reverse else pd.Series(array) #reverse Array if needed and convertes it to a pandas Series object
    trend  = pd.Series(array).rolling(len(array)-1).mean().dropna().reset_index(drop=True)             #calculate MA from array
    return -1 if trend[0] > trend[1] else 1 if trend[0] < trend[1] else 0

The function returns 1 for uptrends, -1 for downtrends and 0 if neither of those are given.

According to my measurements, using your arrays from above, this function takes about 0.002 seconds per call.