|
<< Click to Display Table of Contents >> SERIES |
![]() ![]()
|
The SERIES statement alters timeseries variables (often just called 'series'). Series variables have no starting symbol like % (scalars) or # (collections), may include a frequency indicator !, for instance x!q for x in a quarterly version. When Gekko starts up, the default frequency is annual, so x will be understood as x!a. A Gekko series can have annual (a), quarterly (q), monthly (m), weekly (w), daily (d) or undated (u) frequency. Multidimensional array-series are supported.
Guide: timeseries For an easier introductory guide on Gekko timeseries, see this page. For an introductory guide on array-timeseries, see this page. |
Some main capabilities regarding series statements:
•Timeseries will use the global time setting regarding the time period they are calculated over (cf. TIME), unless a local time period is indicated in the <>-option field, for instance x!q <2020q1 2025q4> = 100;.
•Individual observations may be picked out with for instance x[2020q1], where 2020q1 is a date, and lags/leads use for instance x[-1] or x[+1] (lags/leads must always start with - or + inside the []-indexer).
•You may use a list of values on the right-hand side, for instance x = 1, -2, 3; Otherwise, series statements are math-like, for instance x = y * pch(z);, where pch() is the percentage growth rate (z/z[-1]-1)*100.
•Databanks may be stated with colon (:), for instance x = b1:y + b2:z;, but note that a bankless variable like for instance y or z in the statement x = y + z; may be searched for in other databanks than the first-position databank, cf. the databank search page.
•In addition to normal timeseries, Gekko has array-series, too. Array-series allow the use of multidimensional indexes, for instance x[a,b], picking out a sub-series with a in the first dimension and b in the second dimension. This could be for instance input-output cells, indicating the providing sector a and receiving sector b of intermediate goods. The sub-series x[a,b], or the longer notation x['a','b'], is internally a normal series (with "parent" series x).
•In dynamically accumulating statements like x = x[-1] + 1; a <dyn> option is needed for the statement to accumulate: x <dyn> = x[-1] + 1;. If omitted, Gekko will issue an error.
•Keys [Tab] or [Ctrl+Space] offer autocompletion on timeseries names, also regarding array-series indexes (cf. here).
•Gekko timeseries support data-tracing, making it possible to trace a series value backwards in time to its origins.
variable <period operator KEEP=... LABEL=... SOURCE=... UNIT=... STAMP=... DYN MISSING=...> = expression;
variable[date] = expression; //updating for one period
variable[indexes] = expression; //array-series
f(variable) = expression; //left-side functions like dif(), pch(), dlog(), log()
series ?; //show an overview series count from all open databanks
period |
(Optional). Local period, for instance 2010 2020, 2010q1 2020q4 or %per1 %per2+1. |
operator |
The operator can be d, p, m, q, mp, l or dl. See the 'Operators' section below. |
KEEP= |
If <keep=p> is used, Gekko will keep the growth rate of the left-hand series intact after the period over which the series is updated. For instance, x <2020 2025 m keep=p> = 100; will add 100 to x over the period 2020-25. The keep=p setting makes sure that the growth rate of x regarding 2026 and later already existing observations in x is the same as before the update. Use <keep=d> for absolute change. |
LABEL= |
(Optional). Label (string) for the series, cf. DOC. |
SOURCE= |
(Optional). Source (string) for the series, cf. DOC. |
UNIT= |
(Optional). Unit (string) for the series, cf. DOC. If you prefer, you may use units=... instead of unit=.... |
STAMP= |
(Optional). Stamp (string) for the series, cf. DOC. |
DYN |
(Optional). With this option, lagged dependent/endogenous variables like x[-1] in the expression x = x[-1] + 1; accumulate over time. Using <dyn> entails a speed penalty, so please do not use if not needed (in this particular case, x ^= 1;, x <d>= 1; or dif(x) = 1; could be used instead). The following two are equivalent:
Using <dyn> x <2021 2023 dyn> = x[-1] + 1; //the <dyn> option implicitly runs the expression three times
Explicit x <2021 2021> = x[-1] + 1; //these three lines are equivalent to the use of <dyn> above
Starting from Gekko 3.1.7, statements like x = x[-1] + 1; must have an indication of whether they are to be run dynamically or not, cf. the page on dynamic statements for much more information on such 'dynamics errors' and how to handle them. |
MISSING= |
(Optional). With <missing = ignore>, SERIES will deal with missing array sub-series and missing data values like GAMS, treating them as zero for sums and mathematical expressions. The following options are set locally and reverted afterwards: option series array calc missing = zero; option series data missing = zero. An analogous <missing=ignore> option can also be used for PRT, PLOT, SHEET, CLIP, and DECOMP. See also the appendix page on missings. |
variable |
Left-side name |
expression |
Any expression |
In addition to = (assignment), the following variants can also be used (see the 'Operators' section below):
• += add to existing • -= subtract from existing • *= multiply to existing • /= divide from existing • ^= set absolute time change • %= set percent time change • #= add to percent time change |
|
•If no period is given inside the <...> angle brackets, the global period is used (cf. TIME).
•If a variable on the right-hand side of = is stated without databank, Gekko may look for it in the list of open databanks (if databank search is active, cf. MODE).
•Looping: with a list like for instance #m = a, b;, you may use y{#m} = 1/(1 + x{#m}); to calculate ya from xa, and yb from xb.
Normal series
For an easier introductory guide, see this page. Normal series look like the following example:
x = 100; |
In that case, 100 is assigned to each observation in the global time period (cf. TIME). Different values for each observation can be assigned like this:
time 2021 2023; |
The right-hand side of the x series in this example is a comma-separated sequence of simple numbers. Beware that if you want to use a sequence of expressions, you must use a list definition (and lists are enclosed in parentheses, cf. the example above).
You may indicate a local time period in the <>-option field:
time 2020 2030; |
The local time period overrules the global period. If the three values corresponded to quarters for a quarterly series x, the statement x!q <2021q1 2021q3> = 100, 110, 90; could be used. Alternatively, one could change the global frequency first like this: option freq q; x = 100, 110, 90;. In that case, you do not need to use the frequency indicator x!q explicitly, since !q is added implicitly to x in all places where the frequency is not stated. Note that the example above sets the label of x to 'Gekko-variable' (cf. also DOC).
The right-hand side of a series variable can be any legal Gekko expression that evaluates to a series, or anything that evaluates to a list of values of a suitable length. For list values, you may repeat them using rep, for instance y = 1, 2 rep 2, 3; is equal to y = 1, 2, 2, 3;. The last value in a list may be indicated with rep * which will repeat the item a suitable number of times, if the left-hand side is a series. For instance: y <2021 2025> = 1, 2, 3 rep *;, where the series will get values 1, 2, 3, 3, 3 over the period 2021-25.
Series names may be composed with {}-curlies, representing characters. For instance:
time 2010 2012; |
The statement x{%i} = x1{%i} + x2{%i}; has %i inserted, like x{'a'} = x1{'a'} + x2{'a'}; which reduces to xa = x1a + x2a;. In a similar way, the y{#i} = ... statement runs over 'a' and 'b', respectively. In the prt statement, option <n> is used to omit showing percentage growth, and it should also be noted that #i = a, b; is a short-hand for the stricter #i = ('a', 'b'); (cf. LIST).
Printing also works with {}-curlies:
time 2010 2012; |
Array-series
For an easier introductory guide on array-timeseries, see this page. The dimensions of an array-series need to be stated when it is constructed. Afterwards, indexes are used to refer to its elements:
x = series(2); //two dimensions |
As seen, you may use the shorter x[a,b] instead of the more strict x['a','b'], when the elements are simple names, for instance not containing blanks or special symbols.
When dealing with timeseries given in some logical structure apart from time (for instance input-output cells), name composition is often used, for instance using the name convention xab and xao instead of x[a,b] and x[a,o]. Using array-series, there are convenient aggregation functions like sum(#j, x[a,#j]), summing up the second dimension of the array-series x (for instance, with #j = b, o; the index x[a,#j] will correspond to x[a,b], x[a,o]). The same kind of logic can also be implemented with name-conventions, for instance sum(#i, xa{#j}), where xa{#j} will correspond to xab, xao. Still, array-series can be very practical in order to organize timeseries in some non-time structure/dimensions, and an array-subseries like for instance x[a,b] can be used in the same way as a normal timeseries xab. Also, with array-series there is no risk of name-collisions. For instance, x[ab,c] is clearly different from x[a,bc], whereas a simple naming convention will produce the same name, xabc.
Elements that are simple numbers represented as strings may have values added or subtracted, for instance x[#a+1], where #a could be a list of strings representing ages, like ('18', '19', ..., '80'). You may also perform simple mathematical operations on array-series without indexes, for instance p * x in the above example, being equivalent to p[#i, #j] * x[#i, #j]. Such possibilities (array-series algebra) will be augmented.
Because array-series are bundled together, you might use prt x; to print all the elements (sub-series) of x, delete x; to delete all the x array-series, etc. The GAMS syntax regarding array-series is very similar, which is no coincidence.
The following tables presents different useful operators:
Type |
Operator |
Example |
Result |
Note |
Absolute |
^= |
x ^= 1200; |
x = x[-1] + 1200 |
Same as <d> or dif(x) = 1200;. See also the <dyn> option. |
Relative |
%= |
x %= 3.5; |
x = x[-1]*(1+3.5/100) |
Same as <p> or pch(x) = 3.5;. See also the <dyn> option. |
Absolute |
+= |
x += 1200; |
x = x + 1200 |
Same as <m>. You can also use -= to subtract values. |
Relative |
*= |
x *= 1.03; |
x = x*1.03 |
Similar to <q>. You can also use /= to divide with values. |
Change in relative |
#= |
x #= 2.1; |
x = x[-1]*(x0/x0[-1] + 2.1/100) |
Same as <mp>. See also the <dyn> option. |
In the formula regarding the # operator, x0 is the original timeseries, and x is the new one. Alternatively, the so-called 'short' operators may be used:
Type |
Option |
Example |
Result |
Note |
Absolute |
<d> |
x <d>= 1200; |
x <dyn> = x[-1] + 1200 |
Same as ^=. or dif(x) = 1200;. See also the <dyn> option. |
Relative |
<p> |
x <p>= 3.5; |
x <dyn> = x[-1]*(1+3.5/100) |
Same as %= or pch(x) = 3.5;. See also the <dyn> option. |
Absolute |
<m> |
x <m>= 1200; |
x = x + 1200 |
Same as +=. You can also use -= to subtract values. |
Relative |
<q> |
x <q>= 3; |
x = x*(1+3/100) |
Similar to *=. You can also use /= to divide with values.
|
Change in relative |
<mp> |
x <mp>= 2.1; |
x <dyn> = x[-1]*(x0/x0[-1] + 2.1/100) |
Same as #=. See also the <dyn> option. |
Log |
<l> |
x <l>= 5; |
x = exp(5) |
Same as log(x) = 5;. |
Relative |
<dl> |
x <dl>= 0.035; |
x <dyn> = x[-1]*exp(0.035) |
Same as dlog(x) = 0.035;. |
There are also left-side functions:
Type |
Option |
Example |
Result |
Note |
Absolute |
dif() |
dif(x) = 1200; |
x <dyn> = x[-1] + 1200 |
Same as ^= or <d>=. See also the <dyn> option. You may use diff() as synonym. |
Relative |
pch() |
pch(x) = 3.5; |
x <dyn> = x[-1]*(1+3.5/100) |
Same as %= or <p>=. See also the <dyn> option. |
Log |
log() |
log(x) = 5; |
x = exp(5) |
Same as <l>=. |
Relative |
dlog() |
dlog(x) = 0.035; |
x <dyn> = x[-1]*exp(0.035) |
Same as <dl>=.
|
Compute a quantity q from a volume v and a price p:
time 2010 2013; |
Create a series with a given growth rate:
time 2011 2013; |
Compare with values from the Ref (reference) databank (cf. databanks):
time 2011 2013; |
In the last PRT, @x is short for ref:x, that is, x from the Ref databank. To change a series value in only one period, you may use:
x[2020] = %v; //%v is a scalar value |
This will only set the 2020-value, and will work regardless of what the global time period might be. The above statement is functionally equivalent to the following:
x <2020 2020> = %v |
The $-operator can be used to "control" expressions, like an implicit IF-statement. For instance:
#m = a, b; %v = 10; |
In the y1-statement, y will be 3 if the condition is true (if 'b' is a member of #m and %v has the value 10), and else y will obtain the value 0. In the y2-statement, the whole statement is skipped if the condition is false, and in that case y will not exist at all. Note this conceptual difference regarding $-condition to the left of or to the right of =.
The $-operator can be used to switch between values inside a period, for instance:
time 2001 2005; |
The y1-statement illustrates the use of the $-operator for switching. The last y2-statement illustrates how to perform the same operation using the iif() function. The operation could alternatively be performed with FOR and IF statements, looping explicitly over each period, but using the $-operator or the iif() function is much more convenient here.
Adding 1000 to a series jx can be done with the + operator, or the <m> option:
jx <2010 2010> += 1000; |
Instead of updating with raw numbers, you may use scalar variables instead (in this case, you have to use parentheses to indicate the list, because the elements are not simple numbers):
%f1 = 0.02; |
Using a list of strings #m:
time 2010 2012; |
Note that 1.02 is implicitly used for all three periods (you do not need to write (1.02, 1.02, 1.02)). Note also the {}-curlies in {#m} = (100, 80, 110);. Without the curlies, #m would become a list of the three values 100, 80, 110, which is not the intention. In <2010 2012> {#m} *= 1.02;, without the curlies, the expression would fail, since a list does not implement the *= operator. Finally, in prt {#m};, without the curlies, Gekko would print the strings 'x1' and 'x2', not the series x1 and x2.
If convenient, you may also use wildcard lists:
{'j*'} <2010 2010> = 0; |
This sets all variables in the Work databank beginning with j to 0, for the given period.
You may set timeseries in other databanks than the first-position databank (typically Work), for instance:
bank1:x = 100; |
This will set the variable x to 100 in the bank bank1 (cf. the OPEN statement), provided that the bank writeable. If you need to change timeseries in the Ref databank, you may use the @-indicator for convenience:
@x = 200; |
This will set ref:x to 200 and is short-hand for ref:x = 100;.
Examples, array-series
Array-timeseries comply rather tightly with GAMS syntax, to interface more naturally with GAMS databanks and models. But array-timeseries have many other uses, for instance when downloading multi-dimensional data, or reading data from px-files (PC-Axis), cf. the IMPORT statement.
An array-series can be thought of as a parent series, containing sub-series in one or more dimensions, where these sub-series are accessed with (lists of) simple names. For instance, x may be a one-dimensional array-series, containing the sub-series x[a] and x[b]. These sub-series are like any other normal timeseries, just stored inside the array-series. You may use single quotes for element access, so x[a] = x['a'], x[b] = x['b'], etc. Using quotes is the strict form, and using quotes, the element names may include any characters, for instance x['ab ? x22'].
The following is an example of the use of array-series. In the example, #i and #j are lists of strings containing the sets of names spanning the dimensions, in this case a 3 x 3 structure [#i, #j] like this:
[a, a] [a, b] [a, o]
[b, a] [b, b] [b, o]
[o, a] [o, b] [o, o]
The last part of the example below illustrates how to use default sets (via the map #default). In order for default sets to work, the array-series must contain domain information.
reset; |
The summing up with sum() is sometimes called a 'roll-up operation', aggregating rows/columns, whereas for instance x[a,#j] would be a so-called 'slice operation'. The in-built functions getelements() and subseries() can be practical if you need to know more about the elements of the sub-series of a given array-series x (for instance, the sub-series x[a,b] has element a in the first dimension, and element b in the second dimension).
You may $-condition on a variable that reflects sparsity in two or more dimensions, too (you may for instance have 193 countries, where only a subset of all combinations trade with each other). The following example illustrates two-dimensional sparsity:
reset; x = series(2); |
In y1, the condition is on the array-series e, whereas in y2 it is on the nested list #e (in GAMS, a nested list would correspond to a multidimensional set). You may alternatively move the dollar condition to the right, for instance y1 = sum((#i, #j), x[#i,#j] $ (e[#i,#j]));. Note that array-series are a bit more lenient regarding the user of integers, which are automatically interpreted as their corresponding strings. Also beware regarding the array-series example that there are settings that makes it possible to omit stating the 0 combinations for e, if these are numerous (option series array calc missing = zero), cf. this page.
Regarding domains, it is easy to remove a single element from a list of strings with for instance #i.remove(%s), where %s is a string. To remove several elements from a list of strings, you may use #i - #j. Hence these $-conditionals can be used for easy removal/skipping of elements:
z = sum(#j, x['a', #j] $ (#j in #j.remove('b'))); |
To print an array-series x1, use either:
disp x1; //shows info regarding dimensions, elements, etc. |
If you need non-existing array-timeseries elements to be implicitly understood as having value 0, you can use option series array calc missing = zero;. In that case, you may use for instance sum(#j, x1[#i,#j]), even if some of the combinations (sub-series) of #i and #j do not exist in x1.
In general, you may print or plot an array-series without indicating the dimensions. You can assign lists to array-series dimensions and afterwards control which elements are printed/plotted via a special map with the name #default. This can be practical if you typically only want to see some of the elements of an array-series, but not all.
reset; |
It can often be practical to put the #default map into the Global databank (that is: global:#default = ...), so that it is generally available irrespective of potential OPEN or READ statements. The #default map shown above will restrict all printing/plotting of array-series that have #s assigned to a dimension as its domain.
If you need to put "normal" timeseries into an array-series or vice versa (or if you are interfacing with multidimensional GAMS/gdx data), you can use the following example:
reset; |
Alias names
It is possible to assign one variable name to another via a special list with the name #alias. This can be practical if, for instance, the users are used to one kind of variable names, but are for instance using a model with another kind of variable names.
option interface alias = yes; //this option must be set |
The #alias list could look like the following file:
--------------- alias.lst -------------------- |
This file is read as a list of lists, equivalent to #alias = (('x1', 'c[s]'), ('x2', 'c[b]'), ('x3', 'y'));. The print prints out x1, x2, and x3 as 100, 200, and 300, respectively, even though the 'real' values are stored inside c[a], c[b], and y.
In Gekko 3.x, series operations are handled in a vector-like fashion. This affects the use of lags in expressions with lagged dependent/endogenous variable:
time 2021 2024; |
The last statement is probably easy enough to understand, but the second-last may seem strange. See much more on this, including illustrations, on the dynamic statements page. There are three easy ways of getting accumulations to work without using the <dyn> tag:
time 2021 2024; |
Still, in some cases it my be practical to be able to use the formulation x = x[-1] + 1 and have it accumulate, for instance if the equation originates from a model equation. For such cases, either use the local option <dyn>, or alternatively use a BLOCK like block series dyn = yes; ... ; end;. Example:
time 2021 2024; |
To guard against errors of this type where the user forgets to use <dyn> or a block series dyn on an expression like x = x[-1] + 1, from version 3.1.7 and onwards, Gekko will check this for the presence of lagged dependent/endogenous variables on the right-hand side and issue a 'dynamics error' if an expression like x = x[-1] + 1 or similar is used without considering the dynamics question. As stated above, there is much more info on this on the dynamic statements page.
Series functions
The following shows dedicated timeseries functions (see also the section "Bank/name/frequency/index manipulations" under functions).
Timeseries functions
Function name |
Description |
Examples |
allMiss(x) |
On a timeseries x, the function returns 1 if all observations are missing values ("no data at all"), else it returns 0. See also isMiss(), fromSeries('dataStart'), and fromSeries('dataStart'). |
time 2021 2023; |
arrayPack(name, lname) |
This function finds all non-array ("normal") timeseries in the first-position databank and puts them into a single 1-dimensional array-series called name. In addition, a list lname is created, containing the names of the "packed" timeseries.
Note that after the function is called, the first-position databank only contains the array-series and the list. See also arrayUnpack(). |
read adambank.gbk; //When writing the gdx file, the adam variable will //have domain names 'adamvars' and 't'. |
arrayUnpack(name) |
This function takes the 1-dimensional array-series called name from the first-position databank and transforms ("unpacks") all the elements of the array-series into normal timeseries. The function deletes the array-series before it returns. See also arrayPack(). |
read <gdx> adambk.gdx; //has adam variable inside |
bankFlatten(t) bankFlatten(bank, t)
|
For the global (or locally given) period, all series and array-series are flattened. This means that over the global (or local) period, all values are set to their value in t. A bank name may be provided: if not, the first-position databank is used. |
time 1960 2022; |
bankReplace(x1, x2) bankReplace(bank, x1, x2) |
For the global (or locally given) period, in all series and array-series, the value x1 is replaced with x2. A bank name may be provided: if not, the first-position databank is used. |
time 1960 2022; |
binary(x) |
Converts a table-like nested list of strings into a corresponding array-series where the present elements (that is, the 'rows' of the nested list) are represented with value 1. The nested list must contain time info as the last element of each sublist. The function can be used to tranform a multidimensional GAMS set into a corresponding array-series. This can be convenient for printing, etc. |
time 2001 2002; |
collapse(x) collapse(x, method) collapse(x, freq) collapse(x, freq, method)
|
Function variant of the COLLAPSE statement, converting from higher to lower frequency. Note possible differences compared to COLLAPSE regarding the use of databanks and time periods.
You may input a frequency (freq), choose from 'a', 'q', 'm', 'w'. If frequency is not indicated, the function will per default collapse from d to m, w to m, m to q, or q to a.
The method argument can be 'total', 'avg', 'first', 'last', 'strict' or 'flex'. The last two of these indicate how missing values are handled. You may combine the first four and the last two of these with -, for instance 'avg-flex' to choose method 'avg' combined with missing handling 'flex'. Note that missing handling 'flex' is currently only available for collapse of daily (!d) series. Regarding these options, see the COLLAPSE statement.
You may use option collapse method = ... ; and option collapse missing d = ... ; to control default values for the method and missing handling. See OPTION.
Returns: series. |
time 2020 2020; |
flatten(x, d) |
Transforms 1 array-timeseries x into n normal timeseries with names reflecting the array-series dimensions and delimiter corresponding to the string argument d. For instance, an array-series npop defined over the two dimensions #sex and #age could contain the element (sub-series) npop[m, 40], which flatten() would turn into the normal series npop_m_40. |
npop = series(1); |
getDomains(x) |
Returns a list of strings (with the number of elements corresponding to the number of dimensions) containing the domain for each dimension of the array-series x, for instance '#i' or '*' (the latter means no domain). See also getFixType(), setFixType(), setDomains(). Returns: list |
#d = getdomains(x); //or: #d = x.getdomains(); |
getElements(x) |
Returns a nested list of strings, which for each dimension of the array-series shows which elements occur (in all sub-series). In the example on the right, the first dimension only contains a's, whereas the second dimension contains b and c. The returned list has as many elements as the dimensionality of the array-series. See also subseries(). |
x = series(2); prt x.getelements()[2]; // 'b', 'c' prt x.getelements()[2][1]; // 'b' |
getFixType(x) |
Returns the "fix" type of an array-timeseries x, where the return value can be 'variable' or 'parameter'. Array-series imported from GAMS gdx can be of variable or parameter type. See also setFixType(), getDomains(), setDomains(). Returns: string. |
//See example under setFixType() |
getParent(x) |
For an array-subseries x, its parent series is returned. See example. |
x = series(1); |
hpfilter(x, lambda) hpfilter(<t1 t2>, lambda) hpfilter(x, lambda, log) hpfilter(<t1 t2> x, lambda, log) |
Returns a HP-filtered version of series x. Lambda is normally 6.25 for annual, 1600 for quarterly, and 129600 for monthly series. An additional argument 0 or 1 may be added (1 if log-transforms are to be used inside the calculation). Time period may be indicated with t1 and t2. Returns: series |
y = hpfilter(x, 6.25); |
interpolate(x) interpolate(x, method) interpolate(x, freq) interpolate(x, freq, method) |
Function variant of the INTERPOLATE statement, converting x from lower to higher frequency. Note possible differences compared to INTERPOLATE regarding the use of databanks and time periods.
Method must be 'total' or 'avg' (optionally combined with Olsette/Cholette/Denton, for instance 'total-olsette' or 'avg-cholette').
Destination freq must be 'q', 'm', 'w', or 'd'. Per default, interpolate() will transform from a to q, q to m, m to d and w to d.
Returns: series. |
time 2020 2021; |
isArraySeries(x) |
Returns 1 if the variable x is an array-series, and 0 otherwise. |
x = series(1); |
isTimelessSeries(x) |
Returns 1 if the variable x is a timeless series, and 0 otherwise. |
x = timeless(100); |
laspchain(plist, qlist, t) laspchain(<t1 t2>, plist, qlist, t) laspchain(<t1 t2>, plist, qlist, t, option)
laspchain(vals, valsLag, t) laspchain(<t1 t2>, vals, valsLag, t) |
Laspeyres chain index for quantities. Can be used with either (a) two lists of strings, or (b) two timeseries. In both cases the result is a map containing two consistent aggregated series p and q (price and quantity). The price is set = 1 in the t period. A period can be indicated in the <t1 t2> field. The function is robust regarding missing values at the start or end of the time period.
(a): Two lists of strings (names)
The names inside the two lists indicate the series that are to be aggregated.
See also the bottom of the LIST help page.
(b): Two series (accumulation)
A different way to use the function is to input one series (vals) with values in current prices, and one series (valsLag) with values in the previous period's prices. From this, Gekko will compute the aggregate price and quantity.
If you need to fill out holes (missings) between non-missings, for instance in prices series, you can use the smooth() function or SMOOTH statement.
Quarterly data
For quarterly data, using two lists of strings, option 'annualoverlap' must be indicated. When quarterly data are input, the so-called annual overlap method is used, where the algorithm starts out collapsing the quarterly data into annual data, then computes a "normal" annual chain index for the aggregate price, and lastly uses this annual price index to compute the quarterly indexes.
Returns: map |
time 2017 2020; |
laspfixed(plist, qlist, t) laspfixed(<t1 t2>, plist, qlist, t) laspfixed(<t1 t2>, plist, qlist, t, option) |
Laspeyres fixed-price index. As laspchain(), but with fixed prices. Cannot be used with series input.
Returns: map |
//See example regarding laspchain() |
percentile(x, v) |
Computes the v percentile for the series x, for the global time period. Any missing values within that sample are ignored. Setting v = 0.5 results in the median. Returns: val |
%z = percentile(y, 0.25); |
rebase(x, t) rebase(x, t, index) |
Function variant of the REBASE statement. Note possible differences compared to REBASE regarding the use of databanks and time periods.
You cannot use start/end dates with this function, only a single date (alternatively, use REBASE statement).
Returns: series. |
time 2020 2022; |
rename(x, cfg) |
For an array-series x: the function renames and reorders dimension elements, according to a cfg list (possibly as a listfile). See example. |
//Given this listfile: |
reorder(x, ord) |
For array-series x, this function reorders the dimensions according to the list ord. The list must contain the integers 1..n, where n is the dimensionality of the array-series.
Note: for an array-series dimension of size n, if reorder() is fed with the list (1, 2, ... , n), the function returns an identical array-series. |
x = series(3); //has been moved to the last dimension of y, and //the other two dimensions are moved forwards. |
replace(x, v1, v2) |
For the series or array-series x, the function replaces the value v1 with the value v2, over the given sample.
See also iif(), isMiss(), and the $-conditional.
Returns: series
|
time 2001 2003; |
rotate(x, d) |
Transforms the array-series x to a new array-series, where the time dimension and dimension number d swap places.
For instance, the array-series pop may contain sub-series for each age group 0 to 100, that is, pop['0'], pop['1'], ... , pop[100']. These 101 sub-series are all defined over a time period, say 2020-2050. Then profile = rotate(pop, 1); will be a new array-series containing sub-series for each time period 2020 to 2050, that is, profile['2020'], profile['2021'], ... , profile['2050']. These 31 sub-series are all defined over an undated time period 0 to 100, corresponding to the age dimension. Hence, plot <0u 100u> profile['2020']; will plot the age profile of the population in the year 2020.
See example under PLOT (age profiles section). Returns: series |
//pop is a 1-dimensional array-series |
series(freq, n) |
Constructs a series or array-series of the given frequency and with the given dimensions (n). You can skip some of these options, see examples.
See also isArraySeries().
Returns: series
|
x = series('q', 3); //quarterly array-series, 3-dim |
setDomains(x, d) |
Uses a list of strings (d) to set the domains for each dimension of the array-series x. Use '*' to indicate a domain-less dimension (in GAMS called the universal set), but otherwise each element should start with symbol # (to indicate that it is a list). See also getFixType(), setFixType(), getDomains(). Returns: nothing |
#d = ('#b', '#x'); |
setFixType(x, type) |
Sets the "fix" type of an array-timeseries x, where type can be 'variable' or 'parameter'. When exporting an array-series to a GAMS gdx file, this difference is of significance. See also getFixType(), getDomains(), setDomains(). |
x = series(1); |
smooth(x) smooth(x, method) smooth(x, y) smooth(x, method, y) |
Function variant of the SMOOTH statement to fill holes (missing values) in the series x. Note possible differences compared to SMOOTH regarding the use of databanks and time periods.
Method must be 'linear', 'geometric', 'repeat', 'spline', or 'overlay'. If method is not stated, 'linear' is default. The y variable can be a series, value or 1x1 matrix (y is only used for 'overlay' smoothing).
Returns: series. |
z = x.smooth('linear'); //user linear smoothing |
splice(x1, x2, ...) splice(x1, t1, x2, ...) splice(x1, t1, t2, x2, ...) splice(type, x1, ...) |
Function variant of the SPLICE statement to splice two or more overlapping timeseries x1, x2, ... into one resulting timeseries. Note possible differences compared to SPLICE regarding the use of databanks and time periods.
Type can be 'rel1', 'rel2', 'rel3', 'abs' for the method, or 'first', 'last', '1', '2', '3', etc. for indicating the "primary" series number (such numbers must be strings). You may combine the method and "primary" indication with -, for instance 'rel3-first' or 'abs-2'. Default is 'rel1-last'. See many more details under SPLICE.
Returns: series. |
time 2001 2005;
//Regarding the left-hand side series, //note that splice() never inserts //So this time period is respected, //in contrast to the SPLICE statement.
|
subseries(x, option) |
Helper function for array-series x.
•option = 'elements': nested list of strings with element combinations for each sub-series. •option = 'names': list of sub-series names (as strings). You may remove the frequency part of these names with removefreq(), see example. •option = 'length': the number of sub-series inside the array-series. •option = 'dimensions': the number of dimensions of the array-series.
See also getelements(). |
x = series(2); prt x.subseries('dimensions'); |
timeless(freq, v) |
Constructs a timeless series of the given frequency freq, with value v. You can skip some of these options, see examples.
In many cases, you can just use a value scalar with the same functionality. But timeless series can be practical, for instance they can be used as array-series.
See also isTimelessSeries().
Returns: series
|
x = timeless('q', 3); //quarterly timeless series, with value = 3. |
Note
See the page with syntax diagrams if the basics of names, expressions, etc. is confusing.
In addition to operators += and *=, you can also use their inverse counterparts: -= and /=. So x -= 2; is the same as x = x - 2;, and x /= 2; is the same as x = x / 2;. This is standard in most computer languages. But please note that x ^= 2; is not the same as x = x ^ 2;, that is, x in the second power.
If any of the right-hand side variables are not found (searching depends upon mode), the statement will exit with an error, unless you set option series array calc missing = ...; or option series normal calc missing = ...;. If some of the variables have missing values (shown as 'M' when printing), the left-hand side will become missing as well (for the periods affected).
You may use m() to indicate a missing value, for instance y = m();.
Regarding $-conditions to the right of =, these always evaluate to 0 if the condition is false. On the other hand, regarding a $-condition to the left of =, the whole statement is skipped if the condition is false. Note however that such skipping does not apply intra-series regarding $ to the left of =. So in a statement like y $ (x > 100) = 2 * x; the y series will attain the value 0 in the periods where x <= 100, and the value 2 * x otherwise. If you need y to remain untouched when x <= 100, you may instead use y = iif(x, '>', 100, 2 * x, y);, cf. the iif() function.
Regarding variable types and the Gekko type system, see the VAR section. In this appendix, variable assignment rules, including variable types, is explained in more detail.
A Gekko array-series can be though of as a nested dictionary/map, cf. this:
•Gekko: m = series(2); m[a,x] = 1; m[a,y] = 2; m[b,x] = 3; m[b,y] = 4; prt m[a,x];
•R: nested named list, m <- list(a = list(x = 1, y = 2), b = list(x = 3, y = 4)); print(m$a$x); print(m[['a']][['x']]);. The elements here are numbers and not sub-series, but the idea is similar.
•Python: nested dict.
Related options
option freq = a;
option missing = error;
option series array calc missing = error;
option series array print missing = error;
option series array table missing = error;
option series data missing = m;
option series dyn check = yes;
option series failsafe = no;
option series normal calc missing = error;
option series normal print missing = error;
option series normal table missing = m;
fromSeries()
Related statements
COPY, CREATE, DELETE, DISP, DOC, INDEX, PLOT, PRT, RENAME, SHEET, TIME, VAL