Numpy: Select columns two by two

Viewed 55

I'm working on beginner data analysis with numpy on Python. I've this piece of code:

## column = [product]
## row = [client]
## value 1 means that a product has been purchased .
 
cart = np.array([[1, 1, 1, 1],
                 [1, 0, 1, 1],
                 [1, 1, 0, 0],
                 [0, 1, 1, 1]])

I want to know how can I select the columns above two by two to print at the end how much each pairs of products were purchased. Also I need to find which pair of products was the most purchased.

Where each tuple (u, v, n) means that products u and v are purchased together n times (per n customers). The output will be:

[(0,1,2), (0,2,2), (0,3,2), (1,2,2), (1,3,2), (2,3,3)]
(2,3,3) ->  the most purchased.

Thanks.

2 Answers

You will have to loop on every pair combination. This is essentially range(cart.shape[1]) x range(cart.shape[1]), i.e two for loops.

For a given product index u the corresponding vector is cart[:, u]. To compare two products vectors we can apply the dot product: cart[:, u]*cart[:,v]. The resulting vector will hold a 1 if both products were bought by the same client. To count the number of clients having bought both of these products, we can sum the vector.

Here is the expanded version:

p = range(cart.shape[1])
res = []
for u in p:
  for v in p:
    if u < v:
      res.append((u, v, sum(cart[:,u]*cart[:,v])))  

Or in one go with a list comprehension:

p = range(cart.shape[1])
[(u, v, sum(cart[:,u]*cart[:,v])) for u in p for v in p if u < v]

Here's a quick and easy solution which produces the list of purchase pairs and the most purchased.

Essentially the code just iterates the column pairs (created by combinations), and sums each pair. The pairs whose sum equals 2, are summed to derive the count of sold pairs.

Setup:

a = np.array([[1, 1, 1, 1],
              [1, 0, 1, 1],
              [1, 1, 0, 0],
              [0, 1, 1, 1]])

Sample code:

from itertools import combinations

results = []
for i, j in combinations([0, 1, 2, 3], 2):
    results.append((i, j, (a[:,[i,j]].sum(axis=1) == 2).sum()))
    
max_ = max(results, key=sum)

print(results)
print(f'Max result: {max_}')

Output:

[(0, 1, 2), (0, 2, 2), (0, 3, 2), (1, 2, 2), (1, 3, 2), (2, 3, 3)]
Max result: (2, 3, 3)
Related