Getting the count of a mode of a list - simulation

I am trying to get the value of a mode of a list. I know I can get the mode of a list by using the mode operator in a way such as "show modes [1 2 2 2 2 3 4]" which will report 2 as the mode, but how would I get the count for that mode, 4 in this case since their are 4 2's. I suppose I could get the mode and iterate through the list checking to see if each number is equal the mode, but I am just wondering if there is a simpler way.
Thanks in advance!

A combination of length and filter should get you what you want:
let xs [1 2 2 3 3 4]
foreach modes xs [
let mode ?
let n length filter [ ? = mode ] xs
print (word "mode: " mode ", occurrences: " n)
]
Will output:
mode: 2, occurrences: 2
mode: 3, occurrences: 2
(Of course, by definition, each mode will have the same number of occurrences.)

Related

iter function over table as input - does order matter and why?

I'm totally new to kdb+/q, and I found this problem below quite confusing to me. Just to simplify, we say we have this one line function f returns an one-row table with preset values, and I want to run this function over a combination of inputs x and y, like dates (list) and metas (table, with columns like orderid, px, size etc).
Now, I listed two ways to do so below. Since the function f doesn't really use any of the input, I would suppose the order of x and y doesn't matter since the difference is just which one is passed to f before another and only when two inputs passed would f starts to operate.
But why I got error in the second way, i.e. table follows the list?
Any idea and explanation is much appreciated.
f: {[x;y]
([] m: enlist `M; n: enlist `N)
};
x: 1 2 3;
y: ([] a: 4 5 6; b: 7 8 9);
raze raze f ' [y] ' [x]; // this one works
raze raze f ' [x] ' [y]; // this one gives ERROR: length Explanation: Arguments do not conform
What you're doing is effectively equivalent to:
f:{y;1};
q)(f'[([]a:1 2 3;b:4 5 3)])#/:1 2 3
1 1 1
1 1 1
1 1 1
(using extra brackets to make it clear the order of operation).
In this situation each one reduces to
q)f'[([]a:1 2 3;b:4 5 3);1]
1 1 1
q)f'[([]a:1 2 3;b:4 5 3);2]
1 1 1
q)f'[([]a:1 2 3;b:4 5 3);3]
1 1 1
The "length" is ok here because the "y" values are atomic and kdb automatically expands those atomic values to match the length of the table. In order words, kdb treats these as:
q)f'[([]a:1 2 3;b:4 5 3);1 1 1]
1 1 1
q)f'[([]a:1 2 3;b:4 5 3);2 2 2]
1 1 1
q)f'[([]a:1 2 3;b:4 5 3);3 3 3]
1 1 1
However, when you change the order it becomes:
(f'[1 2 3])#/:([]a:1 2 3;b:4 5 3)
which is equivalent to:
f'[1 2 3;`a`b!1 4]
f'[1 2 3;`a`b!2 5]
f'[1 2 3;`a`b!3 3]
but now you do have a length problem because the dictionaries in the "y" variable are not atomic, they have length 2. Which doesn't match the length of the list (3).
You don’t say so but it looks like you are studying how to iterate a binary function f over list arguments, which has brought you to projecting f' onto x, which gives you a unary f'[x] that you then iterate over y. If that’s how we got here, what you want might be as simple as x f'y, which iterates f over corresponding items in x and y.
However, you mention combinations of inputs. If you want effectively a Cartesian product based on f, then combine the iterators Each Right and Each Left to get x f:/:\:y.
That returns a matrix. You have razed your result. Depending on your argument types, you might be able to use cross to generate all the argument pair combinations, and Apply Each .' to apply f to each pair:
f .' x cross y

How to join strings in a table in kdb?

I would like to join string in kdb but didn't work well. This is the data:
tab:([]service:`CS`CS.US`CS.US_ABC;y:1 2 3)
`CS 1
`CS.US 2
`CS.US_ABC 3
I would like to add :0 and :primary depending on the given parameter. 0 is working now
update service:`$(((string[service],'(":"))),'("C"$string 0)) from tab
If I would like the data to become
`CS:primary 1
`CS.US:primary 2
`CS.US_ABC:primary 3
and the primary is either string or symbol, how could I join?
I am parameterizing the 0 and primary.
Currently, 0 works as follows
update service:`$(((string[service],'(":"))),'( "0")) from tab
but "primary" is not working
update service:`$(((string[service],'(":"))),'( "primary")) from tab
Your query gives you a length error:
q)tab:([]service:`CS`CS.US`CS.US_ABC;y:1 2 3)
q)update service:`$(((string[service],'(":"))),'( "primary")) from tab
'length
[0] update service:`$(((string[service],'(":"))),'( "primary")) from tab
^
This happens because ,' (concatenate each) expects vectors of equal length on both sides, but gets a table column size (3) vector on the left and a character vector of length 7 on the right. Notice what happens when you pass 3 characters:
q)update service:`$(((string[service],'(":"))),'( "pri")) from tab
service y
-------------
CS:p 1
CS.US:r 2
CS.US_ABC:i 3
Each row gets a different suffix. What you want is to use ,\: (concatenate each-left):
q)update service:`$(((string[service],'(":"))),\:( "primary")) from tab
service y
-------------------
CS:primary 1
CS.US:primary 2
CS.US_ABC:primary 3
Why does it work for "0"? It works because "0" is not a vector but a character scalar
q)type "0"
-10h
q)type "primary"
10h
and with a scalar on the right, ,' works the same as .\::
q)"ab",'"0"
"a0"
"b0"
q)"ab",\:"0"
"a0"
"b0"
Finally, your query will run faster if you first prepend ":" to the suffix and then append the result to each service:
q)update service:`$(string[service],\:":","primary") from tab
service y
-------------------
CS:primary 1
CS.US:primary 2
CS.US_ABC:primary 3
If you want primary to be a parameter rather than a fixed string, the following will work (primary is "no" in this example):
q)update {`$string[y],\:":",x}[primary;]service from tab
service y
--------------
CS:no 1
CS.US:no 2
CS.US_ABC:no 3
If primary is a fixed string then you can place it inside the lambda in lieu of "x" and replace "y" with "x", yielding the following:
q)update {`$string[x],\:":","primary"}service from tab
service y
-------------------
CS:primary 1
CS.US:primary 2
CS.US_ABC:primary 3
q)update service:`$(((string[service],'(":"))),'(count[i]#enlist "primary"))
from tab
service y
-------------------
CS:primary 1
CS.US:primary 2
CS.US_ABC:primary 3

how to count number of results in scratch

I am using scratch. I acquire two values from the user and have to find the numbers divisible by 2 & 3 between those values . How can I count those numbers without using arrays ( just by using basic operations) ?
If you only need to count those numbers, arrays are not needed. Just iterate through the range and count:
Here's what you can do (do mind me, I am not good at creating questions and variables) ...
when flag clicked
ask (starting number is?) and wait
set (startrange) to (answer)
ask (ending number is?) and wait
set (endrange) to (answer)
set (counter) to (startrange)
set (divisibleby2) to (0)
set (divisibleby3) to (0)
set (divisibleby6) to (0)
repeat until counter = endrange
if (counter) mod 6 = 0
change (divisibleby6) by (1)
else
if (counter) mod 3 = 0
change (divisibleby3) by (1)
else
if (counter) mod 2 = 0
change (divisibleby2) by (1)
say (join (The number of numbers from the two inputs that are divisible by 2, 3 is) ((divisibleby2) + ((divisibleby3) + (divisibleby6)))
So, why is a divisibleby6 variable needed? It is because some numbers are divisible by 2 and 3 simultaneously, which means, the number would be recorded twice if the code was altered. However, if you want this to happen, this would be the code for you:
hen flag clicked
ask (starting number is?) and wait
set (startrange) to (answer)
ask (ending number is?) and wait
set (endrange) to (answer)
set (counter) to (startrange)
set (divisibleby2) to (0)
set (divisibleby3) to (0)
repeat until counter = endrange
if (counter) mod 3 = 0
change (divisibleby3) by (1)
if (counter) mod 2 = 0
change (divisibleby2) by (1)
say (join (The number of numbers from the two inputs that are divisible by 2, 3 is) ((divisibleby2) + (divisibleby3))

Is it possible to concatenate lists by including one list in another?

I have two lists that will be created during runtime. I want to combine the lists that have been made so that the data can be accessed later on within the code , with the end goal of simplifying my code and improving my model efficiency. Can lists be concatenated by the inclusion of one within the other or is there another way?
Thanks.
The usual way to concatenate lists is by using the sentence primitive. This will give you a new list made with the elements of your two original lists, like in Jen's answer.
Alternatively, you could use the list primitive to build a list with your two original lists included as sub-lists.
The following example shows both methods:
to setup
let list1 [ 1 2 3 ]
let list2 [ 4 5 6 ]
print sentence list1 list2 ; will print: [1 2 3 4 5 6]
print list list1 list2 ; will print: [[1 2 3] [4 5 6]]
end
Which one you should prefer depends, of course, on what you want to do with it...
The sentence command can combine two lists without brackets left
to setup
let mylist1 [1 2 3]
let mylist2 [4 5 6]
set mylist1 sentence mylist1 mylist2
show mylist1
end

Reshape (#) doesn't work with a dynamic argument

To form a matrix consisting of identical rows, one could use
x:1 2 3
2 3#x,x
which produces (1 2 3i;1 2 3i) as expected. However, attempting to generalise this thus:
2 (count x)#x,x
produces a type error although the types are equal:
(type 3) ~ type count x
returns 1b. Why doesn't this work?
The following should work.
q)(2;count x)#x,x
1 2 3
1 2 3
If you look at the parse tree of both your statements you can see that the second is evaluated differently. In the second only the result of count is passed as an argument to #.
q)parse"2 3#x,x"
#
2 3
(,;`x;`x)
q)parse"2 (count x)#x,x"
2
(#;(#:;`x);(,;`x;`x))
If you're looking to build matrices with identical rows you might be better off using
rownum#enlist x
q)x:100000?100
q)\ts do[100;v1:5 100000#x,x]
157 5767696j
q)\ts do[100;v2:5#enlist x]
0 992j
q)v1~v2
1b
I for one find this more natural (and its faster!)