Formula basics
Formulas are a special language used on Conjointly to perform tasks such as:
- Adding calculated variable in your experiment,
- Calculating revenue in the simulator,
- Weighting respondents,
- Piping, including in redirects.
The language is inspired by R. While knowledge of R is not required, those familiar with R will find it easy to use formulas on Conjointly. One key difference is a much more relaxed approach to data types. For example, 1 + "2" is not allowed in R, but it is allowed on Conjointly and returns 3.
You can test and debug your formulas using the Interactive debugger tab in Preview mode. The debugger can also be accessed by adding ?debugger=on to your survey URL, for example https://conjointly.online/study/629614/2yttrza1hv4k2mzvx2lb?debugger=on.
There are only four data types in formulas:
- Numbers (e.g.
1,2.5,-3.14), which are always treated as double-precision floating point numbers (“numeric” type in R). However, for comparisons, precision is limited to six decimal places. - Strings (e.g.
"hello","world"). All operations on them are case-insensitive. - Booleans (i.e.
TRUEorFALSE). - Undefined, which is a special value that is returned when a variable is not defined. When formulas are used in piping inside the survey, an undefined value will be shown as 🤷.
Algebraic functions
Algebraic functions perform basic mathematical operations. They always return a number.
| Operation | Syntax | Example usage | Result |
|---|---|---|---|
| Addition | x+y | 20+15 | 35 |
| Subtraction | x-y | 10-3 | 7 |
| Multiplication | x*y | 7*3 | 21 |
| Division | x/y | 10/2 | 5 |
| Exponential | x^y | 4^2 | 16 |
Important notes:
- Just like in R, if the supplied value is a string, it is converted to a number. If the string cannot be converted to a number, the result is
0. +does not work as a concatenator.- If either argument is
undefined, the result isundefined. - All numbers are treated as double-precision floating point numbers (“numeric” type in R).
- If a vector of numbers is supplied, operation is done on the first element of the vector only.
Example usages of algebraic functions are provided below.
| Situation | Formula | Result | Comment |
|---|---|---|---|
The GET variable gender is male | GETvariable("gender") * 5 | 0 | because male is forced into 0 |
The GET variable gender was not recorded | GETvariable("gender") * 5 | 0 | because the empty string is forced into 0 |
The GET variable age is 20 | GETvariable("age") * 5 | 100 | because age is converted into the number 20 |
"3" + 5 | 8 | because 3 is forced into the number 3 | |
"male" + " bird" | 0 | because + does not work as a concatenator |
Max and min functions
The max and min functions return the minimum or maximum value from a set of arguments. They always return a number.
| Function | Description | Example usage | Result |
|---|---|---|---|
max(item1, item2, [item3], ...) | Returns the highest value among the provided arguments | max(3, -9, 7.5) | 7.5 |
min(item1, item2, [item3], ...) | Returns the lowest value among the provided arguments | min(3, -9, 7.5) | -9 |
Important notes:
- The functions require at least 2 arguments.
- A maximum of 500 arguments are allowed; if more are provided, only the first 500 are considered.
- All arguments are converted to numbers following these rules:
- All numbers are treated as double-precision floating point numbers (“numeric” type in R).
- Strings that can be converted to numbers are converted (e.g.,
"25"becomes25). - Strings that cannot be converted to numbers become
0(including empty strings). TRUEis converted to1.FALSEis converted to0.undefinedvalues are converted to0.- If a vector of numbers is supplied, operation is done on the first element of the vector only.
- If an argument is a function, it is calculated first and its result is passed as an argument, which is then converted to a number according to the rules described above.
Example usages of min and max functions are provided below:
| Situation | Formula | Result | Comment |
|---|---|---|---|
| Arguments are numbers and string | max(3, -9, "25", 8) | 25 | because string "25" is converted into number 25 |
| Arguments are boolean values | min(TRUE, FALSE) | 0 | because TRUE is forced into 1, FALSE is forced into 0 |
| Arguments are non-numeric strings | max("cat", "", "4") | 4 | because "cat" and "" are forced into 0, "4" is converted into 4 |
| Arguments include vector | max([1, 2, 30, -5], "10", 7) | 10 | because only first element of vector (1) is considered |
| Arguments are vector with boolean | min([FALSE, 2, 3], 10, TRUE) | 0 | because the first element of vector FALSE is forced into 0 |
| Argument includes function | max(wrongFormula(234), -5) | 0 | because wrongFormula returns undefined, which is forced into 0 |
Rounding formulas
Rounding formulas are used to adjust numerical values to a desired precision:
| Function | Description | Example usage | Result |
|---|---|---|---|
round(number) | Returns the value of a number rounded to the nearest integer. | round(1.2345) | 1 (number) |
ceil(number) | Returns the smallest integer greater than or equal to a given number. | ceil(1.2345) | 2 (number) |
floor(number) | Returns the largest integer less than or equal to a given number. | floor(1.2345) | 1 (number) |
toFixed(number,fractionDigits) | Converts a number to a string, retaining the specified number of decimals indicated by the optional parameter fractionDigits, which must be an integer from 0 to 20. If fractionDigits is not given or is misspecified, it is assumed to be 0. | toFixed(1.2345,2) | 1.23 (string) |
Example usages are provided below.
| Situation | Formula | Result | Comment |
|---|---|---|---|
The GET variable gender is male | round(GETvariable("gender")) | 0 | because male is forced into 0 |
The GET variable age is 20.02323212424 | toFixed(GETvariable("age")) | 20 | because age is converted into the number 20.02323212424 |
The GET variable age is 20.02323212424 | toFixed(GETvariable("age"),40) | 20 | because fractionDigits is misspecified and therefore assumed to be 0 |
The GET variable age is 20.02323212424 | toFixed(GETvariable("age"),-1.33) | 20 | because fractionDigits is misspecified and therefore assumed to be 0 |
The GET variable freq is -23.31 | ceil(GETvariable("freq")) | -23 | because ceil rounds up |
Comparison operators
Comparison operators are used to compare two variables. Comparisons operators always return TRUE or FALSE.
| Operation | Syntax | Example usage | Result |
|---|---|---|---|
| Equals | x==y | 5==10 | FALSE |
| Not equals | x!=y | 10!=3 | TRUE |
| Greater than | x>y | 5>19 | FALSE |
| Equal to or greater than | x>=y | 4>=4 | TRUE |
| Less than | x<y | 6<10 | TRUE |
| Equal to or less than | x<=y | 5<=1 | FALSE |
| Between (Non-inclusive of bounds) | y<x<z | 4<2<8 | FALSE |
Rules for comparing strings:
- For the
==and!=operators:- If one of the supplied values is a string, it is converted to a number. If the string cannot be converted to a number, it will be forced to
0. - If both variables are strings, the comparison is done alphabetically. For example,
"a"=="b"returnsFALSEand"a"=="a"returnsTRUE. Comparison is case-sensitive.
- If one of the supplied values is a string, it is converted to a number. If the string cannot be converted to a number, it will be forced to
- For other operators, strings are converted to numbers. If a string cannot be converted to a number, it will be forced to
0.
Important notes:
- If a vector of numbers is supplied, operation is done on the first element of the vector only.
- Precision of numbers is limited to six decimal places. It is achieved by checking if the absolute value of differences is greater than one millionth.
- False values work as in JavaScript:
undefinedwill be equated to0, or"0", for an empty string, orFALSE(and vice versa).
Example usages of comparison operators are provided below.
| Situation | Formula | Result | Comment |
|---|---|---|---|
The GET variable gender is male | GETvariable("gender") < 5 | TRUE | because male is forced into 0 |
The GET variable gender was not recorded | GETvariable("gender") < 5 | TRUE | because the empty string is forced into 0 |
The GET variable gender was not recorded | GETvariable("gender") == 0 | TRUE | because the empty string is forced into 0 |
The GET variable gender was not recorded | GETvariable("gender") != 0 | FALSE | because the empty string is forced into 0 |
The GET variable age is 20 | GETvariable("age") < 5 | FALSE | because age is converted into the number 20 |
"3" < 5 | TRUE | because 3 is forced into the number 3 | |
"5" < 4 | FALSE | because 5 is forced into the number 5 | |
"5" == 5 | TRUE | because 5 is forced into the number 5 | |
"male" < " bird" | FALSE | because both strings are forced into the number 0 | |
"male" == "Male" | FALSE | because comparison is case-sensitive | |
"male" == "male" | TRUE | ||
"0" == "" | FALSE | because both values are strings and compared as such | |
0 == "" | TRUE | because the empty string is forced into 0 | |
1.0000001 == 1.0000002 | TRUE | because the absolute value of the difference is 0.0000001 < 0.000001 | |
1.0000001 == 1.0000005 | TRUE | because the absolute value of the difference is 0.0000004 < 0.000001 | |
1.0000001 == 1.0000012 | FALSE | because the absolute value of the difference is 0.0000011 > 0.000001 | |
"" == FALSE | TRUE | because both strings are forced into the number 0 |
Boolean operators
Boolean operators are used to combine or exclude comparison operations. Boolean operators always return TRUE or FALSE.
| Operation | Syntax | Example usage | Result |
|---|---|---|---|
| Not | !x | !(10==5) | TRUE |
| And | x&y | TRUE&(10==5) | FALSE |
| Or | x|y | (10<4)|(10>2) | TRUE |
Important notes:
- If a vector of numbers is supplied, operation is done on the first element of the vector only.
- If either argument is not boolean (i.e. a number or a string), it is converted to boolean under the same rules as
x!=0.
Example usages of boolean operators are provided below.
| Situation | Formula | Result | Comment |
|---|---|---|---|
!0 | TRUE | because 0!=0 is FALSE | |
!1 | FALSE | because 1!=0 is TRUE | |
!-1 | FALSE | because -1!=0 is TRUE | |
!"" | TRUE | because ""!=0 is FALSE | |
1|0 | TRUE | ||
9&7 | TRUE | because 9!=0 is TRUE and 7!=0 is TRUE | |
!-0.00000001 | TRUE | because -0.00000001!=0 is FALSE | |
!-0.001 | FALSE | because -0.001!=0 is TRUE | |
The GET variable gender is male | GETvariable("gender") & 5 | FALSE | because male is forced into 0 |
The GET variable gender was not recorded | GETvariable(“gender”) | 5 | TRUE | the empty string is forced into 0, but 5!=0 is TRUE |
The GET variable gender was not recorded | GETvariable(“gender”) | 0 | FALSE | because the empty string is forced into 0 |
The GET variable gender was not recorded | GETvariable("gender") & 0 | FALSE | because the empty string is forced into 0 |
The GET variable age is 20 | !GETvariable("age") | FALSE | because age is converted into the number 20, and 20!=0 is TRUE |
if and ifs functions
These functions return values depending on whether a condition is true or not:
if('condition', 'then', ['else'])checks condition and returns a value if it isTRUEor a different value if it isFALSE.ifs('condition1', 'then1', ['condition2'], ['then2'], ..., ['else'])returns a value that corresponds to the first TRUE condition, or the “else” value if all specified conditions areFALSE.
Conditions can be specified using comparison operators. If a condition is not boolean (i.e. a number or a string), it is converted to boolean under the same rules as x!=0.
If the “else” value is not specified, it is assumed to be undefined. If an undefined value is returned in a redirect formula, the redirect is not performed.
Example usages of if are provided below:
| Formula | Result | Comment | |
|---|---|---|---|
if(3,3,5) | 3 (number) | because 3!=0 is TRUE | |
if(0,3,5) | 5 (number) | because 0!=0 is FALSE | |
if(FALSE,4,"male") | male (string) | ||
if(FALSE,4) | undefined | ||
if(TRUE,4,"male") | 4 (number) | ||
if(answer(234),4,"male") (but question 234 is not part of this experiment) | male (string) | because undefined!=0 is FALSE | |
if(wrongFormula(234),4,"male") | undefined | because the function wrongFormula does not exist |
Example usages of ifs are provided below:
| Formula | Result | Comment | |
|---|---|---|---|
ifs(3,3,5,3,0) | 3 (number) | because 3!=0 is TRUE | |
ifs(0,3,5,4,-1) | 5 (number) | because 0!=0 is FALSE, but 5!=0 is TRUE | |
ifs(FALSE,4,TRUE,"male") | male (string) | ||
ifs(FALSE,4) | undefined | because the “else” condition is empty here | |
ifs(TRUE,4) | 4 (number) | ||
ifs(TRUE,4,"male") | 4 (number) | ||
ifs(answer(234),4,"male") (but question 234 is not part of this experiment) | undefined | because undefined!=0 is FALSE, but so is "male"!=0 and the “else” condition is empty here | |
ifs(wrongFormula(234),4,"male") | undefined | because the function wrongFormula does not exist |