excelindexingcountmatchlookup

How to count if a product is bought on the same day, by the same person, together with another product?


I've been browsing multiple different places to try and find an answer but I think I'm likely too thick and/or over simplifying how Excel works.

What I'm trying to get is hopefully a matrix, unless there is a better way where I can see in this example, how many times a product has been bought on the same day, by the same customer together with another product.

This is what the data looks like:

A B C
1 Client Name Booking Date Product Name
2 John 2/26/2024 Product 1
3 John 2/26/2024 Product 1
4 John 2/26/2024 Product 2
5 John 2/26/2024 Product 3
6 John 2/26/2024 Product 4
7 John 3/30/2024 Product 1
8 John 4/11/2024 Product 2
9 John 4/11/2024 Product 3
10 Dave 6/24/2024 Product 3
11 Dave 6/24/2024 Product 1
12 Dave 6/24/2024 Product 3
13 Dave 6/24/2024 Product 1
14 Dave 7/17/2024 Product 2
15 Dave 7/17/2024 Product 1
16 Bob 6/6/2024 Product 1
17 Bob 6/6/2024 Product 2
18 Bob 6/8/2024 Product 2
19 Bob 6/8/2024 Product 3

I've tried to implement various countifs and xlookups to no real avail, and I'm starting to think I'm asking too much.

This is how I expect the outcome to be:

1 Product 1 Product 2 Product 3 Product 4
2 Product 1 2 3 2 1
3 Product 2 3 0 3 1
4 Product 3 2 3 1 1
5 Product 4 1 1 1 0

Explanation of the outcome for Product 2:

1st buy:
John 2/26/2024 together with: Product 1 (twice, but counts as 1x together), not together with Product 2 (it needs to be more than 1 of itself to count as together with), together with Product 3 and together with Product 4.

This counts as {1,0,1,1}.

2nd buy:
John 4/11/2024 together with: Product 1, no; Product 2; no, Product 3, yes, Product 4, no.

This counts as {0,0,1,0}.

3rd buy:
Dave 7/17/2024 together with: Product 1, yes; Product 2, no, 3 & 4, no.

This counts as {1,0,0,0}.

4th buy:
Bob 6/6/2024 together with: 1, yes; 2, no; 3, no; 4, no.

This counts as {1,0,0,0}.

5th (last) buy:
Bob 6/8/2024 together with: 1, no; 2, no; 3, yes; 4, no.

This counts as {0,0,1,0}.

Summed by column (product) makes: {3,0,3,1}

Any way around this that isn't overtly complex, does this request make sense?? Thank you!


Solution

  • It's possible, but not easy (thanks for the challenge!):

    =LET(data,A2:C19, ab,TAKE(data,,1)&INDEX(data,,2), c,DROP(data,,2), u,UNIQUE(c),
    REDUCE(HSTACK("",TOROW(u)), u,
           LAMBDA(d,e,
           LET(f,FILTER(HSTACK(data,ab),ISNUMBER(XMATCH(ab,FILTER(ab,c=e)))),
               r,IFNA(REDUCE(0, UNIQUE(INDEX(f,,4)),
                      LAMBDA(x,y,
                      LET(z,FILTER(INDEX(f,,3),INDEX(f,,4)=y),
                          s,UNIQUE(DROP(SORTBY(z,INDEX(z,,1)<>e),1)),
                          VSTACK(x,
                                 IFERROR(MMULT(SEQUENCE(,ROWS(s),,0),N(s=TOROW(u))),0))))),0),
           VSTACK(d,
                  HSTACK(e, BYCOL(r,SUM)))))))
    

    This loops through the unique products e, filters name & date & product rows where the product column contains the current product e.

    Next it loops through the unique name & dates and adds 1 to the product's count if it was bought together with current product e (where 1 bought of e does not count as together).

    enter image description here

    I figured this could be simplified (I think) a bit using MAKEARRAY:

    =LET(a,A2:A19, b,B2:B19, c,C2:C19, p,UNIQUE(c), n,ROWS(p),
    VSTACK(HSTACK("",
                  TOROW(p)),
           HSTACK(p,
                  MAKEARRAY(n,n,LAMBDA(v,w,
                        LET(z,INDEX(p,v),
                            SUM(BYROW(UNIQUE(FILTER(a&b,c=z)),LAMBDA(x,LET(f,FILTER(c,1-ISNA(XMATCH(a&b,x))),SUM(N(IFERROR(UNIQUE(DROP(SORTBY(f,f<>z),1)),"")=INDEX(p,w)))))))))))))
    

    (probably more user friendly:)

    =LET(client,A2:A19,
         booking,B2:B19,
         product,C2:C19,
         uniqueproduct,UNIQUE(product),
         unqprodrows,ROWS(uniqueproduct),
    VSTACK(
           HSTACK("",
                  TOROW(uniqueproduct)),
           HSTACK(uniqueproduct,
                  MAKEARRAY(unqprodrows,     unqprodrows,
                     LAMBDA(verticalcounter, horizontalcounter,
                        LET(currentrowproduct,INDEX(uniqueproduct,verticalcounter),
                            SUM( BYROW(UNIQUE(FILTER(client&booking,product=currentrowproduct)),
                                LAMBDA(nthbuy,
                                   LET(nthbuyfilterincludingself,FILTER(product,1-ISNA(XMATCH(client&booking,nthbuy))),
                                       SUM(
                                           N(IFERROR( UNIQUE(DROP(SORTBY(nthbuyfilterincludingself,nthbuyfilterincludingself<>currentrowproduct),1)) ,"")
                                             =INDEX(uniqueproduct,horizontalcounter)))))))))))))