0

Given an input like this:

timestamp     vars 
2             [1,2,3]
2             [1,2,4]
3             [1,2]
4             [1,3]
5             [1,3]

I need to keep a rolling count of each of the indices. The tried expanding the array into a one hot encoding ([1,2,3,5] -> [0,1,1,1,0,1]) and adding but this can get arbitrarily big (> 1 million), so I want to maintain it as a dict. Something like below. Any pointers would be greatly appreciated.

timestamp     vars 
2             {1:1, 2:1, 3:1}
2             {1:2, 2:2, 3:1, 4:1}
3             {1:3, 2:3, 3:1, 4:1}
4             {1:4, 2:3, 3:2, 4:1}
5             {1:5, 2:3, 3:3, 4:1}

Thanks!

tanyabrown
  • 29
  • 8

2 Answers2

0

Sample Dataframe :

+---+------------+
| ID|         arr|
+---+------------+
|  1|         [0]|
|  2|      [0, 1]|
|  3|   [0, 1, 2]|
|  4|[0, 1, 2, 3]|
|  1|         [0]|
|  1|         [0]|
|  3|   [0, 1, 2]|
|  0|          []|
+---+------------+

Using the following function which uses Collection counter:

def arr_operation(arr):
   from collections import Counter
   return dict(Counter(arr))

Creating UDF for arr_operation function in the following manner :

udf_dist_count =  udf(arr_operation,MapType(IntegerType(), IntegerType()))

And calling the to create a new column:

final_df = df.withColumn("Dict",udf_dist_count("arr"))

The results will be like :

+---+------------+--------------------------------+
|ID |arr         |Dict                            |
+---+------------+--------------------------------+
|1  |[0]         |[0 -> 1]                        |
|2  |[0, 1]      |[0 -> 1, 1 -> 1]                |
|3  |[0, 1, 2]   |[0 -> 1, 1 -> 1, 2 -> 1]        |
|4  |[0, 1, 2, 3]|[0 -> 1, 1 -> 1, 2 -> 1, 3 -> 1]|
|1  |[0]         |[0 -> 1]                        |
|1  |[0]         |[0 -> 1]                        |
|3  |[0, 1, 2]   |[0 -> 1, 1 -> 1, 2 -> 1]        |
|0  |[]          |[]                              |
+---+------------+--------------------------------+

The argument about collection Counter being slow in a distributed environment has been explained in a good manner in the answer to this question Why is Collections.counter so slow?

-1

I would suggest Counter from collections:

In [1]: from collections import Counter                                                                                                                             

In [2]: count = Counter()                                                                                                                                           

In [3]: count.update([1,2,4])                                                                                                                                       

In [4]: count                                                                                                                                                       
Out[4]: Counter({1: 1, 2: 1, 4: 1})

In [5]: count.update([1,2,3])                                                                                                                                       

In [6]: count                                                                                                                                                       
Out[6]: Counter({1: 2, 2: 2, 4: 1, 3: 1})

In [7]: count.update([2,3,5])                                                                                                                                       

In [8]: count                                                                                                                                                       
Out[8]: Counter({1: 2, 2: 3, 4: 1, 3: 2, 5: 1})
salt-die
  • 806
  • 6
  • 7