tranhungdao12a3
Thành viên tiêu biểu

- Tham gia
- 29/11/07
- Bài viết
- 443
- Được thích
- 421
Sao mình tính không có sản phẩm nào đạt trên 50% của mỗi đơn hàng, không biết mình có hiểu ý sai bạn không? Bạn thử tính tay 1 số sản phẩm đạt trên 50% rồi gửi lên xem.Chào các anh chị!
Em có một câu hỏi nhờ anh chị giúp đỡ:
Em có dữ liệu khách hàng mua hàng các sản phẩm khác nhau, em muốn tìm ra sản phẩm được khách hàng thường xuyên mua, dữ liệu và câu hỏi như sau:
View attachment 286766
Cảm ơn các anh chị nhiều!
(Đoán mò): Định nghĩa về đơn hàng: mỗi ngày mua hàng của 1 khách hàng sẽ tính là 1 đơn hàng,Sao mình tính không có sản phẩm nào đạt trên 50% của mỗi đơn hàng, không biết mình có hiểu ý sai bạn không? Bạn thử tính tay 1 số sản phẩm đạt trên 50% rồi gửi lên xem.
Có nhiều chứ bạn, bạn đếm tổng số đơn hàng của khách hàng, sau đó sản phẩm nào xuất hiện >=1/2 số đơn hàng thì nó là sản phẩm thường xuyên thôiSao mình tính không có sản phẩm nào đạt trên 50% của mỗi đơn hàng, không biết mình có hiểu ý sai bạn không? Bạn thử tính tay 1 số sản phẩm đạt trên 50% rồi gửi lên xem.
Bạn tính vậy cũng được, do dữ liệu một số dòng phần số lượng =0 mình quên không sửa.(Đoán mò): Định nghĩa về đơn hàng: mỗi ngày mua hàng của 1 khách hàng sẽ tính là 1 đơn hàng,
vì thế Distinccount đơn hàng của khách hàng sẽ là
View attachment 286804
Logic tính vậy sẽ phức tạp anh. Theo em logic thử như vầy:Bài này viết code còn thấy gian nan.
Giả sử "các sản phẩm được mua cùng nhau" tạm xét theo cặp (2 loại sản phẩm).
Xét dữ liệu của 1 khách hàng.
Đầu tiên, lọc danh sách các mặt hàng xuất hiện nhiều hơn 1 lần ở các đơn hàng.
Tạo danh sách các cặp sản phẩm từ danh sách vừa lọc được ở bước trên.
Xét từng cặp sản phẩm đó, đếm số lần xuất hiện của chúng trong tất cả các đơn hàng. Đối chiếu số lần xuất hiện và xuất kết quả.
---
Trường hợp 3, 4, ..., n các sản phẩm được mua cùng nhau thì làm tương tự. Rất phức tạp.
Trường hợp = 50% thì cũng có thể chúng không được mua cùng nhau đâu.... tiếp đó sẽ so sánh nếu sản phẩm đó xuất hiện >=50% số đơn hàng của khách hàng là được.
Bạn làm cái Sales/Customer Analysis như thế này bắt buộc phải rõ quy trình Hóa đơn và Thanh toán Hóa đơn. Sau đó thiết kế CSDL, cố gắng chuẩn hóa đến bậc 3. Từ đó mới tính tiếp được....
Logic tính vậy sẽ phức tạp anh. Theo em logic thử như vầy:
...
Theo một cách logic như đã diễn giải thì có thể dùng Power Bi phân tích được, vấn đề phát sinh với dữ liệu lớn và hàng trăm sku, nếu nó chạy tổ hợp như vậy rất là nặng máy, nếu chạy 1,2 cái câu hỏi như vậy thì khả năng dẫn đến ngồi chơi xơi nước. Em vẫn nghĩ R hay Python sẽ mạnh hơn trong cái khoản phân tích này dù sao Power Bi chủ yếu mạnh mẽ ở phần trực quan hóa thôi. Em tìm kiếm giải pháp ngoài Power BiBạn làm cái Sales/Customer Analysis như thế này bắt buộc phải rõ quy trình Hóa đơn và Thanh toán Hóa đơn. Sau đó thiết kế CSDL, cố gắng chuẩn hóa đến bậc 3. Từ đó mới tính tiếp được.
Cái này làm xuôi rót hay không là do kỹ năng thiết kế bảng chứ không phải các công thức Excel hay VBA.
Nếu là bài toán đoán Mẫu (Model) thì dùng file CSV và dùng R hay Python. Đương nhirn là nếu chịu bỏ tiền ra thì có cả đống phần mềm chuyên nghiệp để tính.
Khách hàng | Tổng đơn | Sản phẩm | Lượng đơn |
---|---|---|---|
S0005360 | 26 | C-PIE02P | 19 |
S0005360 | 26 | C-PIE06P | 23 |
S0005360 | 26 | C-PIE12P | 26 |
S0005360 | 26 | CSTS06P | 21 |
S0005360 | 26 | CSTS12P(8) | 24 |
S0005360 | 26 | OStarKim Chi - Small | 14 |
S0005360 | 26 | OStarS.W - Small | 18 |
S0005360 | 26 | SwingNYSteak-Small | 16 |
S0005361 | 21 | C-PIE12P | 15 |
S0005361 | 21 | OStarS.W - Normal | 12 |
S0005361 | 21 | OStarS.W - Small | 11 |
S0005361 | 21 | SwingNYSteak - Normal | 11 |
S0005361 | 21 | SwingNYSteak-Small | 11 |
S0005362 | 24 | C-PIE06P | 14 |
S0005362 | 24 | C-PIE12P | 17 |
S0005362 | 24 | CSTS06P | 13 |
S0005362 | 24 | CSTS12P(8) | 17 |
S0005362 | 24 | OStarS.W - Normal | 14 |
S0005362 | 24 | OStarS.W - Small | 17 |
S0005362 | 24 | SwingNYSteak - Normal | 15 |
S0005362 | 24 | SwingNYSteak-Small | 17 |
S0005366 | 26 | C-PIE06P | 18 |
S0005366 | 26 | C-PIE12P | 23 |
S0005366 | 26 | CSTS06P | 21 |
S0005366 | 26 | CSTS12P(8) | 21 |
S0005366 | 26 | OStarKim Chi - Small | 16 |
S0005366 | 26 | OStarS.W - Small | 20 |
S0005366 | 26 | SwingChicken - Small | 15 |
S0005366 | 26 | SwingNYSteak-Small | 19 |
S0005367 | 25 | C-PIE02P | 15 |
S0005367 | 25 | C-PIE12P | 21 |
S0005367 | 25 | CSTS12P(8) | 19 |
S0005367 | 25 | OStarKim Chi - Small | 16 |
S0005367 | 25 | OStarS.W - Small | 17 |
S0005367 | 25 | SwingNYSteak-Small | 14 |
S0005373 | 26 | C-PIE06P | 15 |
S0005373 | 26 | C-PIE12P | 21 |
S0005373 | 26 | CSTS12P(8) | 17 |
S0005373 | 26 | OStarKim Chi - Small | 18 |
S0005373 | 26 | OStarPMai-TMuoi - Small | 14 |
S0005373 | 26 | OStarS.W - Small | 21 |
S0005373 | 26 | SwingNYSteak-Small | 23 |
S0005374 | 11 | OStarS.W - Small | 6 |
S0005375 | 26 | C-PIE02P | 16 |
S0005375 | 26 | C-PIE06P | 20 |
S0005375 | 26 | C-PIE12P | 25 |
S0005375 | 26 | CSTS02P | 14 |
S0005375 | 26 | CSTS06P | 17 |
S0005375 | 26 | CSTS12P(8) | 26 |
S0005375 | 26 | OStarKim Chi - Small | 20 |
S0005375 | 26 | OStarNatural - Small | 20 |
S0005375 | 26 | OStarPMai-TMuoi - Small | 22 |
S0005375 | 26 | OStarS.W - Small | 26 |
S0005375 | 26 | SwingNYSteak-Small | 25 |
S0005379 | 23 | C-PIE12P | 15 |
S0005379 | 23 | CSTS12P(8) | 13 |
S0005379 | 23 | OStarPMai-TMuoi - Small | 12 |
S0005379 | 23 | OStarS.W - Small | 17 |
S0005379 | 23 | SwingNYSteak - Normal | 13 |
S0005379 | 23 | SwingNYSteak-Small | 17 |
S0005380 | 23 | C-PIE06P | 13 |
S0005380 | 23 | C-PIE12P | 14 |
S0005380 | 23 | CSTS12P(8) | 15 |
S0005381 | 24 | OStarKim Chi - Normal | 18 |
S0005381 | 24 | OStarS.W - Normal | 18 |
S0005381 | 24 | OStarS.W - Small | 17 |
S0005381 | 24 | SwingChicken-Normal | 13 |
S0005381 | 24 | SwingNYSteak - Normal | 17 |
S0005381 | 24 | SwingNYSteak-Small | 15 |
S0005384 | 20 | C-PIE02P | 13 |
S0005384 | 20 | C-PIE12P | 16 |
S0005384 | 20 | CSTS12P(8) | 14 |
S0005384 | 20 | OStarS.W - Small | 12 |
S0005386 | 21 | C-PIE12P | 11 |
S0005386 | 21 | OStarKim Chi - Small | 13 |
S0005386 | 21 | OStarS.W - Small | 14 |
S0005386 | 21 | SwingNYSteak-Small | 14 |
S0005396 | 25 | C-PIE06P | 16 |
S0005396 | 25 | C-PIE12P | 21 |
S0005396 | 25 | CSTS12P(8) | 18 |
S0005396 | 25 | OStarKim Chi - Small | 16 |
S0005396 | 25 | OStarS.W - Small | 17 |
S0005396 | 25 | SwingNYSteak-Small | 17 |
S0005398 | 14 | C-PIE02P | 8 |
S0005398 | 14 | C-PIE06P | 10 |
S0005398 | 14 | C-PIE12P | 13 |
S0005398 | 14 | CSTS12P(8) | 13 |
S0005401 | 26 | C-PIE06P | 16 |
S0005401 | 26 | C-PIE12P | 21 |
S0005401 | 26 | C-PIE12P(Dark) | 14 |
S0005401 | 26 | CSTS12P(8) | 15 |
S0005401 | 26 | OStarKim Chi - Small | 25 |
S0005401 | 26 | OStarNatural - Small | 25 |
S0005401 | 26 | OStarPMai-TMuoi - Small | 22 |
S0005401 | 26 | OStarS.W - Small | 26 |
S0005401 | 26 | SwingCheese - Small | 16 |
S0005401 | 26 | SwingChicken - Small | 25 |
S0005401 | 26 | SwingMAXX - Bo Small | 16 |
S0005401 | 26 | SwingNYSteak-Small | 26 |
S0005404 | 26 | C-PIE06P | 15 |
S0005404 | 26 | C-PIE12P | 25 |
S0005404 | 26 | CSTS12P(8) | 14 |
S0005404 | 26 | OStarKim Chi - Small | 23 |
S0005404 | 26 | OStarNatural - Small | 18 |
S0005404 | 26 | OStarPMai-TMuoi - Small | 18 |
S0005404 | 26 | OStarS.W - Small | 23 |
S0005404 | 26 | SwingNYSteak-Small | 16 |
S0005415 | 26 | C-PIE02P | 18 |
S0005415 | 26 | C-PIE12P | 25 |
S0005415 | 26 | CSTS02P | 18 |
S0005415 | 26 | CSTS12P(8) | 20 |
S0005415 | 26 | OStarKim Chi - Normal | 14 |
S0005415 | 26 | OStarS.W - Normal | 16 |
S0005415 | 26 | OStarS.W - Small | 16 |
S0005415 | 26 | SwingNYSteak - Normal | 17 |
S0005416 | 26 | C-PIE02P | 14 |
S0005416 | 26 | C-PIE06P | 14 |
S0005416 | 26 | C-PIE12P | 22 |
S0005416 | 26 | CSTS12P(8) | 15 |
S0005416 | 26 | OStarKim Chi - Normal | 19 |
S0005416 | 26 | OStarS.W - Normal | 20 |
S0005416 | 26 | OStarS.W - Small | 14 |
S0005416 | 26 | SwingNYSteak - Normal | 19 |
S0005423 | 26 | C-PIE02P | 26 |
S0005423 | 26 | C-PIE06P | 20 |
S0005423 | 26 | C-PIE12P | 26 |
S0005423 | 26 | C-PIE12P(Dark) | 15 |
S0005423 | 26 | CSTS02P | 24 |
S0005423 | 26 | CSTS06P | 24 |
S0005423 | 26 | CSTS12P(8) | 25 |
S0005423 | 26 | OStarKim Chi - Normal | 21 |
S0005423 | 26 | OStarKim Chi - Small | 24 |
S0005423 | 26 | OStarNatural - Small | 24 |
S0005423 | 26 | OStarPMai-TMuoi - Small | 24 |
S0005423 | 26 | OStarS.W - Normal | 22 |
S0005423 | 26 | OStarS.W - Small | 25 |
S0005423 | 26 | SwingCheese - Small | 17 |
S0005423 | 26 | SwingChicken - Small | 24 |
S0005423 | 26 | SwingChicken-Normal | 16 |
S0005423 | 26 | SwingMAXX - Bo Normal | 14 |
S0005423 | 26 | SwingMAXX - Bo Small | 20 |
S0005423 | 26 | SwingNYSteak - Normal | 21 |
S0005423 | 26 | SwingNYSteak-Small | 25 |
Sản phẩm mua >50% số đơn như này chuẩn rồi anh, Vấn đề là ở câu số 2, cần trích ra sản phẩm nào mà cùng nhau xuất hiện ở >75% số đơn của mỗi khách hàng ý anh!Tôi lập bảng cấu trúc tương tự trên Access. Giả sử mỗi khách hàng trong một ngày chỉ có duy nhất một đơn hàng (có thể nhiều mặt hàng khác nhau), với những sản phẩm xuất hiện trong hơn 1/2 trong tổng số đơn của mỗi khách tôi query được kết quả như thế này. Không biết đúng không nhỉ?
Khách hàng Tổng đơn Sản phẩm Lượng đơn S0005360 26C-PIE02P 19S0005360 26C-PIE06P 23S0005360 26C-PIE12P 26S0005360 26CSTS06P 21S0005360 26CSTS12P(8) 24S0005360 26OStarKim Chi - Small 14S0005360 26OStarS.W - Small 18S0005360 26SwingNYSteak-Small 16S0005361 21C-PIE12P 15S0005361 21OStarS.W - Normal 12S0005361 21OStarS.W - Small 11S0005361 21SwingNYSteak - Normal 11S0005361 21SwingNYSteak-Small 11S0005362 24C-PIE06P 14S0005362 24C-PIE12P 17S0005362 24CSTS06P 13S0005362 24CSTS12P(8) 17S0005362 24OStarS.W - Normal 14S0005362 24OStarS.W - Small 17S0005362 24SwingNYSteak - Normal 15S0005362 24SwingNYSteak-Small 17S0005366 26C-PIE06P 18S0005366 26C-PIE12P 23S0005366 26CSTS06P 21S0005366 26CSTS12P(8) 21S0005366 26OStarKim Chi - Small 16S0005366 26OStarS.W - Small 20S0005366 26SwingChicken - Small 15S0005366 26SwingNYSteak-Small 19S0005367 25C-PIE02P 15S0005367 25C-PIE12P 21S0005367 25CSTS12P(8) 19S0005367 25OStarKim Chi - Small 16S0005367 25OStarS.W - Small 17S0005367 25SwingNYSteak-Small 14S0005373 26C-PIE06P 15S0005373 26C-PIE12P 21S0005373 26CSTS12P(8) 17S0005373 26OStarKim Chi - Small 18S0005373 26OStarPMai-TMuoi - Small 14S0005373 26OStarS.W - Small 21S0005373 26SwingNYSteak-Small 23S0005374 11OStarS.W - Small 6S0005375 26C-PIE02P 16S0005375 26C-PIE06P 20S0005375 26C-PIE12P 25S0005375 26CSTS02P 14S0005375 26CSTS06P 17S0005375 26CSTS12P(8) 26S0005375 26OStarKim Chi - Small 20S0005375 26OStarNatural - Small 20S0005375 26OStarPMai-TMuoi - Small 22S0005375 26OStarS.W - Small 26S0005375 26SwingNYSteak-Small 25S0005379 23C-PIE12P 15S0005379 23CSTS12P(8) 13S0005379 23OStarPMai-TMuoi - Small 12S0005379 23OStarS.W - Small 17S0005379 23SwingNYSteak - Normal 13S0005379 23SwingNYSteak-Small 17S0005380 23C-PIE06P 13S0005380 23C-PIE12P 14S0005380 23CSTS12P(8) 15S0005381 24OStarKim Chi - Normal 18S0005381 24OStarS.W - Normal 18S0005381 24OStarS.W - Small 17S0005381 24SwingChicken-Normal 13S0005381 24SwingNYSteak - Normal 17S0005381 24SwingNYSteak-Small 15S0005384 20C-PIE02P 13S0005384 20C-PIE12P 16S0005384 20CSTS12P(8) 14S0005384 20OStarS.W - Small 12S0005386 21C-PIE12P 11S0005386 21OStarKim Chi - Small 13S0005386 21OStarS.W - Small 14S0005386 21SwingNYSteak-Small 14S0005396 25C-PIE06P 16S0005396 25C-PIE12P 21S0005396 25CSTS12P(8) 18S0005396 25OStarKim Chi - Small 16S0005396 25OStarS.W - Small 17S0005396 25SwingNYSteak-Small 17S0005398 14C-PIE02P 8S0005398 14C-PIE06P 10S0005398 14C-PIE12P 13S0005398 14CSTS12P(8) 13S0005401 26C-PIE06P 16S0005401 26C-PIE12P 21S0005401 26C-PIE12P(Dark) 14S0005401 26CSTS12P(8) 15S0005401 26OStarKim Chi - Small 25S0005401 26OStarNatural - Small 25S0005401 26OStarPMai-TMuoi - Small 22S0005401 26OStarS.W - Small 26S0005401 26SwingCheese - Small 16S0005401 26SwingChicken - Small 25S0005401 26SwingMAXX - Bo Small 16S0005401 26SwingNYSteak-Small 26S0005404 26C-PIE06P 15S0005404 26C-PIE12P 25S0005404 26CSTS12P(8) 14S0005404 26OStarKim Chi - Small 23S0005404 26OStarNatural - Small 18S0005404 26OStarPMai-TMuoi - Small 18S0005404 26OStarS.W - Small 23S0005404 26SwingNYSteak-Small 16S0005415 26C-PIE02P 18S0005415 26C-PIE12P 25S0005415 26CSTS02P 18S0005415 26CSTS12P(8) 20S0005415 26OStarKim Chi - Normal 14S0005415 26OStarS.W - Normal 16S0005415 26OStarS.W - Small 16S0005415 26SwingNYSteak - Normal 17S0005416 26C-PIE02P 14S0005416 26C-PIE06P 14S0005416 26C-PIE12P 22S0005416 26CSTS12P(8) 15S0005416 26OStarKim Chi - Normal 19S0005416 26OStarS.W - Normal 20S0005416 26OStarS.W - Small 14S0005416 26SwingNYSteak - Normal 19S0005423 26C-PIE02P 26S0005423 26C-PIE06P 20S0005423 26C-PIE12P 26S0005423 26C-PIE12P(Dark) 15S0005423 26CSTS02P 24S0005423 26CSTS06P 24S0005423 26CSTS12P(8) 25S0005423 26OStarKim Chi - Normal 21S0005423 26OStarKim Chi - Small 24S0005423 26OStarNatural - Small 24S0005423 26OStarPMai-TMuoi - Small 24S0005423 26OStarS.W - Normal 22S0005423 26OStarS.W - Small 25S0005423 26SwingCheese - Small 17S0005423 26SwingChicken - Small 24S0005423 26SwingChicken-Normal 16S0005423 26SwingMAXX - Bo Normal 14S0005423 26SwingMAXX - Bo Small 20S0005423 26SwingNYSteak - Normal 21S0005423 26SwingNYSteak-Small 25
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
tbl0 = Table.Group(Source, {"Khách hàng"}, {{"Count", each List.Count(List.Distinct([Ngày]))}}),
tbl1 = Table.Group(Source, {"Khách hàng", "Sản Phẩm"}, {{"OderSP", each Table.RowCount(_), Int64.Type}}),
tbl2 = Table.NestedJoin(tbl1, {"Khách hàng"}, tbl0, {"Khách hàng"}, "tbl1", JoinKind.LeftOuter),
tbl3 = Table.ExpandTableColumn(tbl2, "tbl1", {"Count"}, {"TotalOder"}),
tbl4 = Table.AddColumn(tbl3, "DK", each [OderSP]/[TotalOder]),
tbl5 = Table.SelectRows(tbl4, each [DK] > 0.5),
KQ = Table.RemoveColumns(tbl5,{"DK"})
in
KQ
=LET(so,A2:A4386,sp,B2:B4386,sl,C2:C4386,d,D2:D4386,_ab,so&"|"&sp,uso,UNIQUE(so),od_1,MAP(uso,LAMBDA(x,ROWS(UNIQUE(FILTER(d,so=x))))),uss,UNIQUE(_ab),od_2,MAP(uss,LAMBDA(y,ROWS(FILTER(sp,_ab=y)))),kh,TEXTBEFORE(uss,"|"),_sp,TEXTAFTER(uss,"|"),od_3,XLOOKUP(kh,uso,od_1),FILTER(HSTACK(kh,od_3,_sp,od_2),od_2/od_3>0.5))
Cảm ơn bạn, mình chưa xài E365 nên chưa coi công thức được, mình sẽ xem sau khi càiDựa theo kết quả #9
Power Query
Công thức E365Mã:let Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content], tbl0 = Table.Group(Source, {"Khách hàng"}, {{"Count", each List.Count(List.Distinct([Ngày]))}}), tbl1 = Table.Group(Source, {"Khách hàng", "Sản Phẩm"}, {{"OderSP", each Table.RowCount(_), Int64.Type}}), tbl2 = Table.NestedJoin(tbl1, {"Khách hàng"}, tbl0, {"Khách hàng"}, "tbl1", JoinKind.LeftOuter), tbl3 = Table.ExpandTableColumn(tbl2, "tbl1", {"Count"}, {"TotalOder"}), tbl4 = Table.AddColumn(tbl3, "DK", each [OderSP]/[TotalOder]), tbl5 = Table.SelectRows(tbl4, each [DK] > 0.5), KQ = Table.RemoveColumns(tbl5,{"DK"}) in KQ
Mã:=LET(so,A2:A4386,sp,B2:B4386,sl,C2:C4386,d,D2:D4386,_ab,so&"|"&sp,uso,UNIQUE(so),od_1,MAP(uso,LAMBDA(x,ROWS(UNIQUE(FILTER(d,so=x))))),uss,UNIQUE(_ab),od_2,MAP(uss,LAMBDA(y,ROWS(FILTER(sp,_ab=y)))),kh,TEXTBEFORE(uss,"|"),_sp,TEXTAFTER(uss,"|"),od_3,XLOOKUP(kh,uso,od_1),FILTER(HSTACK(kh,od_3,_sp,od_2),od_2/od_3>0.5))
Option Explicit
Sub test()
Dim lr&, i&, j&, k&, s, rng, arr(), id As String, cell As Range
Dim dicKH As Object, dicSP As Object
Set dicKH = CreateObject("Scripting.Dictionary")
Set dicSP = CreateObject("Scripting.Dictionary")
With Sheets("data")
lr = .Cells(Rows.Count, "A").End(xlUp).Row
rng = .Range("A2:D" & lr).Value
ReDim arr(1 To 100000, 1 To 2)
For i = 1 To UBound(rng)
id = rng(i, 1) & "|" & rng(i, 4)
If Not dicKH.exists(id) Then
dicKH.Add id, rng(i, 2)
k = k + 1: arr(k, 1) = rng(i, 1): arr(k, 2) = rng(i, 4)
Else
dicKH(id) = dicKH(id) & "|" & rng(i, 3)
End If
If Not dicSP.exists(rng(i, 2)) Then dicSP.Add rng(i, 2), ""
Next
End With
With Sheets("Tonghop")
.Cells.ClearContents
.Range("B1").Value = Sheets("Data").Range("A1").Value: .Range("C1").Value = Sheets("Data").Range("D1").Value
.Range("B2").Resize(k, 2).Value = arr
.Range("D1").Resize(1, dicSP.Count).Value = dicSP.keys
.Range("D2").Resize(dicKH.Count, dicSP.Count).Formula = "=COUNTIFS(data!$A$2:$A$4387,$B2,data!$D$2:$D$4387,$C2,data!$B$2:$B$4387,D$1)"
rng = .Range("B2").Resize(dicKH.Count, 1).Value
End With
dicKH.RemoveAll
With Sheets("Thongke")
.Cells.ClearContents
.Range("B1").Value = Sheets("Tonghop").Range("B1").Value: .Range("C1").Value = "So don hang"
For i = 1 To UBound(rng)
If Not dicKH.exists(rng(i, 1)) Then
dicKH.Add rng(i, 1), 1
Else
dicKH(rng(i, 1)) = dicKH(rng(i, 1)) + 1
End If
Next
.Range("B2").Resize(dicKH.Count, 1).Value = WorksheetFunction.Transpose(dicKH.keys)
.Range("C2").Resize(dicKH.Count, 1).Value = WorksheetFunction.Transpose(dicKH.items)
.Range("D1").Resize(1, dicSP.Count).Value = dicSP.keys
With .Range("D2").Resize(dicKH.Count, dicSP.Count)
.Formula = "=IF(SUMIF(Tonghop!$B$2:$B$10000,$B2,Tonghop!D$2:D$10000)/$C2>0.5,SUMIF(Tonghop!$B$2:$B$10000,$B2,Tonghop!D$2:D$10000)/$C2,"""")"
.NumberFormat = "0%"
End With
For Each cell In .Range("D1").Resize(1, dicSP.Count)
If WorksheetFunction.Sum(cell.Resize(dicKH.Count, 1)) = 0 Then cell.ClearContents
Next
.Range("D1").Resize(1, dicSP.Count).SpecialCells(xlBlanks).EntireColumn.Delete
End With
End Sub
Anh cho em xin với ạBài này có sẵn bài giải bằng Python rồi đó.
Và có cả bài giải kết hợp Python + Power BI.
Anh cho em xin với ạ
Đây ạ ! Nhìn code cũng hay hay ạ https://github.com/Gaelim/Populatiry-EngineBạn tìm theo từ khoá này nhé.
"Frequently bought together items with Python and Power BI"
Điều kiện >=75% số đơn tức là sản phẩm nào mà cùng nhau xuất hiện ở >=75% số đơn của khách hàng thì trích ra ạ.Bài toán tương đối phức tạp nên mình sẽ làm qua các bước sau:
1- Tạo sheet "Tonghop"
Mỗi đơn hàng là 1 dòng
Mỗi sản phẩm là 1 cột
Nộii dung trong bảng là đếm số lần xuất hiện của mỗi sản phẩm
2- Tạo sheet "Thongke"
Mỗi khách hàng là 1 dòng, và có thống kên số đơn hàng của khách hàng đó
Mỗi sản phẩm là 1 cột. Cho mỗi sản phẩm, thống kê % xuất hiện của sản phẩm đó cho mỗi khách hàng. Chỉ liệt kê số liệu >50%, nếu dưới thì tự động loại bỏ ra.
3- Về yêu cầu trích ra "các SP cùng nhau xuất hiện >75%", mình vẫn chưa hiểu yêu cầu này.
Nếu được thì căn cứ vào các bảng kết quả nói trên, bạn làm tay một vài trường hợp ra xem sao.
PHP:Option Explicit Sub test() Dim lr&, i&, j&, k&, s, rng, arr(), id As String, cell As Range Dim dicKH As Object, dicSP As Object Set dicKH = CreateObject("Scripting.Dictionary") Set dicSP = CreateObject("Scripting.Dictionary") With Sheets("data") lr = .Cells(Rows.Count, "A").End(xlUp).Row rng = .Range("A2:D" & lr).Value ReDim arr(1 To 100000, 1 To 2) For i = 1 To UBound(rng) id = rng(i, 1) & "|" & rng(i, 4) If Not dicKH.exists(id) Then dicKH.Add id, rng(i, 2) k = k + 1: arr(k, 1) = rng(i, 1): arr(k, 2) = rng(i, 4) Else dicKH(id) = dicKH(id) & "|" & rng(i, 3) End If If Not dicSP.exists(rng(i, 2)) Then dicSP.Add rng(i, 2), "" Next End With With Sheets("Tonghop") .Cells.ClearContents .Range("B1").Value = Sheets("Data").Range("A1").Value: .Range("C1").Value = Sheets("Data").Range("D1").Value .Range("B2").Resize(k, 2).Value = arr .Range("D1").Resize(1, dicSP.Count).Value = dicSP.keys .Range("D2").Resize(dicKH.Count, dicSP.Count).Formula = "=COUNTIFS(data!$A$2:$A$4387,$B2,data!$D$2:$D$4387,$C2,data!$B$2:$B$4387,D$1)" rng = .Range("B2").Resize(dicKH.Count, 1).Value End With dicKH.RemoveAll With Sheets("Thongke") .Cells.ClearContents .Range("B1").Value = Sheets("Tonghop").Range("B1").Value: .Range("C1").Value = "So don hang" For i = 1 To UBound(rng) If Not dicKH.exists(rng(i, 1)) Then dicKH.Add rng(i, 1), 1 Else dicKH(rng(i, 1)) = dicKH(rng(i, 1)) + 1 End If Next .Range("B2").Resize(dicKH.Count, 1).Value = WorksheetFunction.Transpose(dicKH.keys) .Range("C2").Resize(dicKH.Count, 1).Value = WorksheetFunction.Transpose(dicKH.items) .Range("D1").Resize(1, dicSP.Count).Value = dicSP.keys With .Range("D2").Resize(dicKH.Count, dicSP.Count) .Formula = "=IF(SUMIF(Tonghop!$B$2:$B$10000,$B2,Tonghop!D$2:D$10000)/$C2>0.5,SUMIF(Tonghop!$B$2:$B$10000,$B2,Tonghop!D$2:D$10000)/$C2,"""")" .NumberFormat = "0%" End With For Each cell In .Range("D1").Resize(1, dicSP.Count) If WorksheetFunction.Sum(cell.Resize(dicKH.Count, 1)) = 0 Then cell.ClearContents Next .Range("D1").Resize(1, dicSP.Count).SpecialCells(xlBlanks).EntireColumn.Delete End With End Sub
Sản phẩm B mua cùng sản phẩm A, ngược lại chưa chắc Sản phẩm A mua cùng sản phẩm BChào các anh chị!
Em có một câu hỏi nhờ anh chị giúp đỡ:
Em có dữ liệu khách hàng mua hàng các sản phẩm khác nhau, em muốn tìm ra sản phẩm được khách hàng thường xuyên mua, dữ liệu và câu hỏi như sau:
Cảm ơn các anh chị nhiều!
Option Explicit
Sub XYZ()
Dim arr(), a, SP(), res(), res2(), dh$, dhSP$, dic As Object, dicDH As Object
Dim sRow&, sR$, i&, j&, r&, id&, jd&, sSP&, k&, k2&, sDon#, iSP#
Set dic = CreateObject("scripting.dictionary")
Set dicDH = CreateObject("scripting.dictionary")
arr = Range("A2", Range("D" & Rows.Count).End(xlUp)).Value
sRow = UBound(arr)
ReDim res(1 To sRow, 1 To 2)
For i = 1 To sRow
If arr(i, 3) > 0 Then
If dic.exists(arr(i, 2)) = False Then
sSP = sSP + 1 'So San Pham
res(sSP, 2) = arr(i, 2)
dic.Add arr(i, 2), sSP
End If
dh = arr(i, 1) & "|" & arr(i, 4)
dhSP = dh & "|" & arr(i, 2)
If dic.exists(dhSP) = False Then
dic.Add dhSP, ""
If dicDH.exists(dh) = False Then
sDon = sDon + 1 'So Don hang
dicDH.Add dh, Array(arr(i, 2))
Else
a = dicDH(dh) 'San Pham cua Don hang
ReDim Preserve a(0 To UBound(a) + 1)
a(UBound(a)) = arr(i, 2)
dicDH(dh) = a
End If
End If
End If
Next i
ReDim SP(1 To sSP, 0 To sSP)
ReDim res2(1 To sSP, 1 To sSP)
For Each a In dicDH.items
sRow = UBound(a)
For i = 0 To sRow
id = dic(a(i))
SP(id, 0) = SP(id, 0) + 1
For j = 0 To sRow
jd = dic(a(j))
If id <> jd Then
SP(id, jd) = SP(id, jd) + 1
End If
Next j
Next i
Next a
sDon = sDon * 0.5 '50% So Don hang
For i = 1 To sSP
If SP(i, 0) > sDon Then
k = k + 1
res(k, 1) = res(i, 2)
End If
iSP = SP(i, 0) * 0.75 '75% So San Pham
jd = 1
For j = 1 To sSP
If SP(i, j) > iSP Then
If jd = 1 Then
k2 = k2 + 1
res2(k2, 1) = res(i, 2)
End If
jd = jd + 1
res2(k2, jd) = res(j, 2)
End If
Next j
Next i
Range("F6").Resize(k) = res 'SP mua thuong xuyên
Range("H6").Resize(k2, sSP) = res2 'Sp mua cung nhau
End Sub
Kết quả như vầy anh ạ:Sản phẩm B mua cùng sản phẩm A, ngược lại chưa chắc Sản phẩm A mua cùng sản phẩm B
Kiểm tra lại
Mã:Option Explicit Sub XYZ() Dim arr(), a, SP(), res(), res2(), dh$, dhSP$, dic As Object, dicDH As Object Dim sRow&, sR$, i&, j&, r&, id&, jd&, sSP&, k&, k2&, sDon#, iSP# Set dic = CreateObject("scripting.dictionary") Set dicDH = CreateObject("scripting.dictionary") arr = Range("A2", Range("D" & Rows.Count).End(xlUp)).Value sRow = UBound(arr) ReDim res(1 To sRow, 1 To 2) For i = 1 To sRow If arr(i, 3) > 0 Then If dic.exists(arr(i, 2)) = False Then sSP = sSP + 1 'So San Pham res(sSP, 2) = arr(i, 2) dic.Add arr(i, 2), sSP End If dh = arr(i, 1) & "|" & arr(i, 4) dhSP = dh & "|" & arr(i, 2) If dic.exists(dhSP) = False Then dic.Add dhSP, "" If dicDH.exists(dh) = False Then sDon = sDon + 1 'So Don hang dicDH.Add dh, Array(arr(i, 2)) Else a = dicDH(dh) 'San Pham cua Don hang ReDim Preserve a(0 To UBound(a) + 1) a(UBound(a)) = arr(i, 2) dicDH(dh) = a End If End If End If Next i ReDim SP(1 To sSP, 0 To sSP) ReDim res2(1 To sSP, 1 To sSP) For Each a In dicDH.items sRow = UBound(a) For i = 0 To sRow id = dic(a(i)) SP(id, 0) = SP(id, 0) + 1 For j = 0 To sRow jd = dic(a(j)) If id <> jd Then SP(id, jd) = SP(id, jd) + 1 End If Next j Next i Next a sDon = sDon * 0.5 '50% So Don hang For i = 1 To sSP If SP(i, 0) > sDon Then k = k + 1 res(k, 1) = res(i, 2) End If iSP = SP(i, 0) * 0.75 '75% So San Pham jd = 1 For j = 1 To sSP If SP(i, j) > iSP Then If jd = 1 Then k2 = k2 + 1 res2(k2, 1) = res(i, 2) End If jd = jd + 1 res2(k2, jd) = res(j, 2) End If Next j Next i Range("F6").Resize(k) = res 'SP mua thuong xuyên Range("H6").Resize(k2, sSP) = res2 'Sp mua cung nhau End Sub
Khách hàng | Tổng đơn | 75% đơn | Số đơn | Sản phẩm mua cùng 75% số Bill |
S0005360 | 26 | 19.5 | 20 đơn | Sản phẩm: CSTS06P,CSTS12P(8) |
S0005360 | 26 | 19.5 | 21 đơn | Sản phẩm: C-PIE06P,C-PIE12P,CSTS06P |
S0005360 | 26 | 19.5 | 22 đơn | Sản phẩm: C-PIE06P,CSTS12P(8) |
S0005360 | 26 | 19.5 | 23 đơn | Sản phẩm: C-PIE06P,C-PIE12P |
S0005360 | 26 | 19.5 | 24 đơn | Sản phẩm: C-PIE12P,CSTS12P(8) |
S0005366 | 26 | 19.5 | 20 đơn | Sản phẩm: C-PIE12P,CSTS12P(8) |
S0005373 | 26 | 19.5 | 21 đơn | Sản phẩm: OStarS.W - Small,SwingNYSteak-Small |
S0005375 | 26 | 19.5 | 20 đơn | Sản phẩm: C-PIE06P,C-PIE12P,CSTS12P(8),OStarKim Chi - Small,OStarNatural - Small,OStarS.W - Small,SwingNYSteak-Small |
S0005375 | 26 | 19.5 | 21 đơn | Sản phẩm: C-PIE12P,OStarPMai-TMuoi - Small,SwingNYSteak-Small |
S0005375 | 26 | 19.5 | 22 đơn | Sản phẩm: CSTS12P(8),OStarPMai-TMuoi - Small,OStarS.W - Small |
S0005375 | 26 | 19.5 | 24 đơn | Sản phẩm: C-PIE12P,SwingNYSteak-Small |
S0005375 | 26 | 19.5 | 25 đơn | Sản phẩm: C-PIE12P,CSTS12P(8),OStarS.W - Small,SwingNYSteak-Small |
S0005375 | 26 | 19.5 | 26 đơn | Sản phẩm: CSTS12P(8),OStarS.W - Small |
S0005381 | 24 | 18 | 18 đơn | Sản phẩm: OStarKim Chi - Normal,OStarS.W - Normal |
S0005398 | 14 | 10.5 | 12 đơn | Sản phẩm: C-PIE12P,CSTS12P(8) |
S0005401 | 26 | 19.5 | 20 đơn | Sản phẩm: C-PIE12P,OStarKim Chi - Small,SwingChicken - Small |
S0005401 | 26 | 19.5 | 21 đơn | Sản phẩm: C-PIE12P,OStarNatural - Small,OStarPMai-TMuoi - Small,OStarS.W - Small,SwingNYSteak-Small |
S0005401 | 26 | 19.5 | 22 đơn | Sản phẩm: OStarKim Chi - Small,OStarPMai-TMuoi - Small,OStarS.W - Small,SwingChicken - Small,SwingNYSteak-Small |
S0005401 | 26 | 19.5 | 24 đơn | Sản phẩm: OStarKim Chi - Small,OStarNatural - Small,SwingChicken - Small |
S0005401 | 26 | 19.5 | 25 đơn | Sản phẩm: OStarKim Chi - Small,OStarNatural - Small,OStarS.W - Small,SwingChicken - Small,SwingNYSteak-Small |
S0005401 | 26 | 19.5 | 26 đơn | Sản phẩm: OStarS.W - Small,SwingNYSteak-Small |
S0005404 | 26 | 19.5 | 22 đơn | Sản phẩm: C-PIE12P,OStarKim Chi - Small,OStarS.W - Small |
S0005404 | 26 | 19.5 | 23 đơn | Sản phẩm: OStarKim Chi - Small,OStarS.W - Small |
S0005415 | 26 | 19.5 | 20 đơn | Sản phẩm: C-PIE12P,CSTS12P(8) |
S0005423 | 26 | 19.5 | 20 đơn | Sản phẩm: C-PIE02P,C-PIE06P,C-PIE12P,CSTS02P,CSTS06P,CSTS12P(8),OStarKim Chi - Normal,OStarKim Chi - Small,OStarNatural - Small,OStarPMai-TMuoi - Small,OStarS.W - Normal,OStarS.W - Small,SwingChicken - Small,SwingMAXX - Bo Small,SwingNYSteak - Normal,SwingNYSteak-Small |
S0005423 | 26 | 19.5 | 21 đơn | Sản phẩm: C-PIE02P,C-PIE12P,CSTS12P(8),OStarKim Chi - Normal,OStarNatural - Small,OStarS.W - Normal,OStarS.W - Small,SwingNYSteak - Normal,SwingNYSteak-Small |
S0005423 | 26 | 19.5 | 22 đơn | Sản phẩm: C-PIE02P,C-PIE12P,CSTS02P,CSTS06P,OStarKim Chi - Small,OStarNatural - Small,OStarPMai-TMuoi - Small,OStarS.W - Normal,SwingChicken - Small |
S0005423 | 26 | 19.5 | 23 đơn | Sản phẩm: CSTS02P,CSTS06P,CSTS12P(8),OStarKim Chi - Small,OStarNatural - Small,OStarPMai-TMuoi - Small,OStarS.W - Small,SwingChicken - Small,SwingNYSteak-Small |
S0005423 | 26 | 19.5 | 24 đơn | Sản phẩm: C-PIE02P,C-PIE12P,CSTS02P,CSTS06P,CSTS12P(8),OStarKim Chi - Small,OStarNatural - Small,OStarPMai-TMuoi - Small,OStarS.W - Small,SwingChicken - Small,SwingNYSteak-Small |
S0005423 | 26 | 19.5 | 25 đơn | Sản phẩm: C-PIE02P,C-PIE12P,CSTS12P(8),OStarS.W - Small,SwingNYSteak-Small |
S0005423 | 26 | 19.5 | 26 đơn | Sản phẩm: C-PIE02P,C-PIE12P |
CSTS06P,CSTS12P(8),
|
Dùng cách vét cạn và tìm cách tăng tốc xử lý nên code khá phức tạp, kết quả liệt kê tất cả các trường hợp mua chungKết quả như vầy anh ạ:
Sản phẩm muốn được trích ra thì nó phải cùng nhau xuất hiện xuất hiện >75% số đơn là được, ví dụ khách hàng S0005360, tổng đơn là 26, 75% đơn là 19.5, tức là cứ xuất hiện cùng nhau 20 đơn trở lên là tách ra: Vậy sản phẩm tách ra là
Khách hàng Tổng đơn 75% đơn Số đơn Sản phẩm mua cùng 75% số Bill S0005360 26 19.520 đơn Sản phẩm: CSTS06P,CSTS12P(8) S0005360 26 19.521 đơn Sản phẩm: C-PIE06P,C-PIE12P,CSTS06P S0005360 26 19.522 đơn Sản phẩm: C-PIE06P,CSTS12P(8) S0005360 26 19.523 đơn Sản phẩm: C-PIE06P,C-PIE12P S0005360 26 19.524 đơn Sản phẩm: C-PIE12P,CSTS12P(8) S0005366 26 19.520 đơn Sản phẩm: C-PIE12P,CSTS12P(8) S0005373 26 19.521 đơn Sản phẩm: OStarS.W - Small,SwingNYSteak-Small S0005375 26 19.520 đơn Sản phẩm: C-PIE06P,C-PIE12P,CSTS12P(8),OStarKim Chi - Small,OStarNatural - Small,OStarS.W - Small,SwingNYSteak-Small S0005375 26 19.521 đơn Sản phẩm: C-PIE12P,OStarPMai-TMuoi - Small,SwingNYSteak-Small S0005375 26 19.522 đơn Sản phẩm: CSTS12P(8),OStarPMai-TMuoi - Small,OStarS.W - Small S0005375 26 19.524 đơn Sản phẩm: C-PIE12P,SwingNYSteak-Small S0005375 26 19.525 đơn Sản phẩm: C-PIE12P,CSTS12P(8),OStarS.W - Small,SwingNYSteak-Small S0005375 26 19.526 đơn Sản phẩm: CSTS12P(8),OStarS.W - Small S0005381 24 1818 đơn Sản phẩm: OStarKim Chi - Normal,OStarS.W - Normal S0005398 14 10.512 đơn Sản phẩm: C-PIE12P,CSTS12P(8) S0005401 26 19.520 đơn Sản phẩm: C-PIE12P,OStarKim Chi - Small,SwingChicken - Small S0005401 26 19.521 đơn Sản phẩm: C-PIE12P,OStarNatural - Small,OStarPMai-TMuoi - Small,OStarS.W - Small,SwingNYSteak-Small S0005401 26 19.522 đơn Sản phẩm: OStarKim Chi - Small,OStarPMai-TMuoi - Small,OStarS.W - Small,SwingChicken - Small,SwingNYSteak-Small S0005401 26 19.524 đơn Sản phẩm: OStarKim Chi - Small,OStarNatural - Small,SwingChicken - Small S0005401 26 19.525 đơn Sản phẩm: OStarKim Chi - Small,OStarNatural - Small,OStarS.W - Small,SwingChicken - Small,SwingNYSteak-Small S0005401 26 19.526 đơn Sản phẩm: OStarS.W - Small,SwingNYSteak-Small S0005404 26 19.522 đơn Sản phẩm: C-PIE12P,OStarKim Chi - Small,OStarS.W - Small S0005404 26 19.523 đơn Sản phẩm: OStarKim Chi - Small,OStarS.W - Small S0005415 26 19.520 đơn Sản phẩm: C-PIE12P,CSTS12P(8) S0005423 26 19.520 đơn Sản phẩm: C-PIE02P,C-PIE06P,C-PIE12P,CSTS02P,CSTS06P,CSTS12P(8),OStarKim Chi - Normal,OStarKim Chi - Small,OStarNatural - Small,OStarPMai-TMuoi - Small,OStarS.W - Normal,OStarS.W - Small,SwingChicken - Small,SwingMAXX - Bo Small,SwingNYSteak - Normal,SwingNYSteak-Small S0005423 26 19.521 đơn Sản phẩm: C-PIE02P,C-PIE12P,CSTS12P(8),OStarKim Chi - Normal,OStarNatural - Small,OStarS.W - Normal,OStarS.W - Small,SwingNYSteak - Normal,SwingNYSteak-Small S0005423 26 19.522 đơn Sản phẩm: C-PIE02P,C-PIE12P,CSTS02P,CSTS06P,OStarKim Chi - Small,OStarNatural - Small,OStarPMai-TMuoi - Small,OStarS.W - Normal,SwingChicken - Small S0005423 26 19.523 đơn Sản phẩm: CSTS02P,CSTS06P,CSTS12P(8),OStarKim Chi - Small,OStarNatural - Small,OStarPMai-TMuoi - Small,OStarS.W - Small,SwingChicken - Small,SwingNYSteak-Small S0005423 26 19.524 đơn Sản phẩm: C-PIE02P,C-PIE12P,CSTS02P,CSTS06P,CSTS12P(8),OStarKim Chi - Small,OStarNatural - Small,OStarPMai-TMuoi - Small,OStarS.W - Small,SwingChicken - Small,SwingNYSteak-Small S0005423 26 19.525 đơn Sản phẩm: C-PIE02P,C-PIE12P,CSTS12P(8),OStarS.W - Small,SwingNYSteak-Small S0005423 26 19.526 đơn Sản phẩm: C-PIE02P,C-PIE12P
Được trích ra từ kết hợp của 20 đơn đến 24 đơn có các sản phẩm cùng nhau.
CSTS06P,CSTS12P(8),
C-PIE06P,C-PIE12P
Khách hàng và sản phẩm khác tương tự vậy
Option Explicit
Sub XYZ()
Dim dic As Object, dic2 As Object, dKH As Object, dDH As Object, dSP As Object
Dim aTH$(), sTH&, sCol&, iMin&
Dim arr(), res(), aDH, aSP, a, b()
Dim dh$, sp$, kh, tmp$
Dim sRow&, sDH&, sDon#, k&, N&, i&, j&, r&, c&, id&, jd&
iMin = -1 'Dieu kien xet cot So luong: So luong >= 0 (iMin = -1), So luong >0 (iMin = 0)
sCol = 10 'Thong thuong: 10 < sCol < 20
Call Creat_TH(aTH, sTH, sCol)
Set dic = CreateObject("scripting.dictionary")
Set dic2 = CreateObject("scripting.dictionary")
Set dKH = CreateObject("scripting.dictionary")
Set dDH = CreateObject("scripting.dictionary")
Set dSP = CreateObject("scripting.dictionary")
arr = Range("A2", Range("D" & Rows.Count).End(xlUp)).Value
sRow = UBound(arr)
ReDim res(1 To sRow, 1 To 5)
For i = 1 To sRow
If arr(i, 3) > iMin Then
kh = arr(i, 1)
dh = kh & "|" & arr(i, 4)
sp = dh & "|" & arr(i, 2)
If dSP.exists(sp) = False Then
dSP.Add sp, ""
If dDH.exists(dh) = False Then
dDH.Add dh, Array(arr(i, 2))
If dKH.exists(kh) = False Then
dKH(kh) = Array(dh)
Else
a = dKH(kh) 'Gan DH moi vao Khach hang
ReDim Preserve a(0 To UBound(a) + 1)
a(UBound(a)) = dh
dKH(kh) = a
End If
Else
a = dDH(dh) 'gán San Pham vào Don hang
ReDim Preserve a(0 To UBound(a) + 1)
a(UBound(a)) = arr(i, 2)
dDH(dh) = a
End If
End If
End If
Next i
For Each kh In dKH.keys
aDH = dKH(kh)
sDH = UBound(aDH) 'So Don Hang
sDon = (sDH + 1) * 0.75 '75% So Don hang
dic.RemoveAll: dic2.RemoveAll
k = 0
For i = 0 To sDH
aSP = dDH(aDH(i))
For j = 0 To UBound(aSP)
sp = aSP(j)
N = dic(sp) + 1
dic(sp) = N
If N > sDon Then
If dic2.exists(sp) = False Then
k = k + 1
dic2.Add sp, k
ReDim Preserve a(1 To k)
a(k) = sp
For c = 0 To sDH
If dSP.exists(aDH(c) & "|" & sp) Then dic2(c & "|" & sp) = ""
Next c
End If
End If
Next j
Next i
If k > 1 Then
If k > sCol Then sCol = k: Call Creat_TH(aTH, sTH, sCol) 'Tao lai TH Lon hon
For i = 1 To sTH
N = aTH(i, 2): If N > k Then Exit For
tmp = aTH(i, 1)
jd = 0: id = 0
For j = 1 To N
If Mid(tmp, j, 1) = "1" Then
jd = jd + 1
ReDim Preserve b(1 To jd)
b(jd) = a(j)
End If
Next j
For c = 0 To sDH
For j = 1 To jd
If dic2.exists(c & "|" & b(j)) = False Then Exit For
Next j
If j = jd + 1 Then id = id + 1 'Dem so don hang cua San pham
Next c
If id > sDon Then
r = r + 1
res(r, 1) = kh
res(r, 2) = sDH + 1
res(r, 3) = sDon
res(r, 4) = id
res(r, 5) = Join(b, ", ")
End If
Next i
End If
Next kh
If Range("H6").Value <> Empty Then Range("H6").CurrentRegion.ClearContents
If r Then Range("H6").Resize(r, 5) = res 'Sp mua cung nhau
End Sub
Sub Creat_TH(aTH, sTH, sCol)
Dim N&, i&, j&, S&, r&, tmp$
ReDim bTH(2 To sCol, 1 To 1)
j = 2
N = 2 ^ sCol - 1
ReDim aTH(1 To N - 2, 1 To 2)
For i = 3 To N
tmp = D2B(i, sCol)
If tmp <> Empty Then
r = r + 1
aTH(r, 1) = StrReverse(tmp)
aTH(r, 2) = j
End If
If i >= S Then
j = j + 1
S = 2 ^ j
End If
Next i
sTH = r
End Sub
Function D2B(num, sCol) As String
Dim qt&, rd&, tmp$, L&
qt = num
Do
rd = qt Mod 2
If rd = 1 Then L = L + 1
qt = Int(qt / 2)
tmp = rd & tmp
Loop Until qt = 0
If L > 1 Then D2B = Format(Val(tmp), String(sCol, "0"))
End Function
Kết quả chưa đúng anh ạ, kết quả trùng lặp nhiều mã, ví dụ kháchS0005423Dùng cách vét cạn và tìm cách tăng tốc xử lý nên code khá phức tạp, kết quả liệt kê tất cả các trường hợp mua chung
Kiểm tra lại kết quả
Mã:Option Explicit Sub XYZ() Dim dic As Object, dic2 As Object, dKH As Object, dDH As Object, dSP As Object Dim aTH$(), sTH&, sCol&, iMin& Dim arr(), res(), aDH, aSP, a, b() Dim dh$, sp$, kh, tmp$ Dim sRow&, sDH&, sDon#, k&, N&, i&, j&, r&, c&, id&, jd& iMin = -1 'Dieu kien xet cot So luong: So luong >= 0 (iMin = -1), So luong >0 (iMin = 0) sCol = 10 'Thong thuong: 10 < sCol < 20 Call Creat_TH(aTH, sTH, sCol) Set dic = CreateObject("scripting.dictionary") Set dic2 = CreateObject("scripting.dictionary") Set dKH = CreateObject("scripting.dictionary") Set dDH = CreateObject("scripting.dictionary") Set dSP = CreateObject("scripting.dictionary") arr = Range("A2", Range("D" & Rows.Count).End(xlUp)).Value sRow = UBound(arr) ReDim res(1 To sRow, 1 To 5) For i = 1 To sRow If arr(i, 3) > iMin Then kh = arr(i, 1) dh = kh & "|" & arr(i, 4) sp = dh & "|" & arr(i, 2) If dSP.exists(sp) = False Then dSP.Add sp, "" If dDH.exists(dh) = False Then dDH.Add dh, Array(arr(i, 2)) If dKH.exists(kh) = False Then dKH(kh) = Array(dh) Else a = dKH(kh) 'Gan DH moi vao Khach hang ReDim Preserve a(0 To UBound(a) + 1) a(UBound(a)) = dh dKH(kh) = a End If Else a = dDH(dh) 'gán San Pham vào Don hang ReDim Preserve a(0 To UBound(a) + 1) a(UBound(a)) = arr(i, 2) dDH(dh) = a End If End If End If Next i For Each kh In dKH.keys aDH = dKH(kh) sDH = UBound(aDH) 'So Don Hang sDon = (sDH + 1) * 0.75 '75% So Don hang dic.RemoveAll: dic2.RemoveAll k = 0 For i = 0 To sDH aSP = dDH(aDH(i)) For j = 0 To UBound(aSP) sp = aSP(j) N = dic(sp) + 1 dic(sp) = N If N > sDon Then If dic2.exists(sp) = False Then k = k + 1 dic2.Add sp, k ReDim Preserve a(1 To k) a(k) = sp For c = 0 To sDH If dSP.exists(aDH(c) & "|" & sp) Then dic2(c & "|" & sp) = "" Next c End If End If Next j Next i If k > 1 Then If k > sCol Then sCol = k: Call Creat_TH(aTH, sTH, sCol) 'Tao lai TH Lon hon For i = 1 To sTH N = aTH(i, 2): If N > k Then Exit For tmp = aTH(i, 1) jd = 0: id = 0 For j = 1 To N If Mid(tmp, j, 1) = "1" Then jd = jd + 1 ReDim Preserve b(1 To jd) b(jd) = a(j) End If Next j For c = 0 To sDH For j = 1 To jd If dic2.exists(c & "|" & b(j)) = False Then Exit For Next j If j = jd + 1 Then id = id + 1 'Dem so don hang cua San pham Next c If id > sDon Then r = r + 1 res(r, 1) = kh res(r, 2) = sDH + 1 res(r, 3) = sDon res(r, 4) = id res(r, 5) = Join(b, ", ") End If Next i End If Next kh If Range("H6").Value <> Empty Then Range("H6").CurrentRegion.ClearContents If r Then Range("H6").Resize(r, 5) = res 'Sp mua cung nhau End Sub Sub Creat_TH(aTH, sTH, sCol) Dim N&, i&, j&, S&, r&, tmp$ ReDim bTH(2 To sCol, 1 To 1) j = 2 N = 2 ^ sCol - 1 ReDim aTH(1 To N - 2, 1 To 2) For i = 3 To N tmp = D2B(i, sCol) If tmp <> Empty Then r = r + 1 aTH(r, 1) = StrReverse(tmp) aTH(r, 2) = j End If If i >= S Then j = j + 1 S = 2 ^ j End If Next i sTH = r End Sub Function D2B(num, sCol) As String Dim qt&, rd&, tmp$, L& qt = num Do rd = qt Mod 2 If rd = 1 Then L = L + 1 qt = Int(qt / 2) tmp = rd & tmp Loop Until qt = 0 If L > 1 Then D2B = Format(Val(tmp), String(sCol, "0")) End Function
Khách hàng | Tổng đơn | 75% đơn | Số đơn | Sản phẩm mua cùng 75% số Bill | |||||||||||||||||||||||||
S0005423 | 26 | 19.5 | 20 đơn | Sản phẩm: C-PIE02P,C-PIE06P,C-PIE12P,CSTS02P,CSTS06P,CSTS12P(8),OStarKim Chi - Normal,OStarKim Chi - Small,OStarNatural - Small,OStarPMai-TMuoi - Small,OStarS.W - Normal,OStarS.W - Small,SwingChicken - Small,SwingMAXX - Bo Small,SwingNYSteak - Normal,SwingNYSteak-Small | |||||||||||||||||||||||||
S0005423 | 26 | 19.5 | 21 đơn | Sản phẩm: C-PIE02P,C-PIE12P,CSTS12P(8),OStarKim Chi - Normal,OStarNatural - Small,OStarS.W - Normal,OStarS.W - Small,SwingNYSteak - Normal,SwingNYSteak-Small | |||||||||||||||||||||||||
S0005423 | 26 | 19.5 | 22 đơn | Sản phẩm: C-PIE02P,C-PIE12P,CSTS02P,CSTS06P,OStarKim Chi - Small,OStarNatural - Small,OStarPMai-TMuoi - Small,OStarS.W - Normal,SwingChicken - Small | |||||||||||||||||||||||||
S0005423 | 26 | 19.5 | 23 đơn | Sản phẩm: CSTS02P,CSTS06P,CSTS12P(8),OStarKim Chi - Small,OStarNatural - Small,OStarPMai-TMuoi - Small,OStarS.W - Small,SwingChicken - Small,SwingNYSteak-Small | |||||||||||||||||||||||||
S0005423 | 26 | 19.5 | 24 đơn | Sản phẩm: C-PIE02P,C-PIE12P,CSTS02P,CSTS06P,CSTS12P(8),OStarKim Chi - Small,OStarNatural - Small,OStarPMai-TMuoi - Small,OStarS.W - Small,SwingChicken - Small,SwingNYSteak-Small | |||||||||||||||||||||||||
S0005423 | 26 | 19.5 | 25 đơn | Sản phẩm: C-PIE02P,C-PIE12P,CSTS12P(8),OStarS.W - Small,SwingNYSteak-Small | |||||||||||||||||||||||||
S0005423 | 26 | 19.5 | 26 đơn | Sản phẩm: C-PIE02P,C-PIE12P |
Code mình liệt kê tất cả các tổ hợp, nếu có 3 sp mua cùng sẽ liệt kê 4 trường hợpKết quả chưa đúng anh ạ, kết quả trùng lặp nhiều mã, ví dụ kháchS0005423
View attachment 287010
Thực tế nó chỉ có những sản phẩm này thôi ah:
Khách hàng Tổng đơn 75% đơn Số đơn Sản phẩm mua cùng 75% số Bill S0005423 26 19.520 đơn Sản phẩm: C-PIE02P,C-PIE06P,C-PIE12P,CSTS02P,CSTS06P,CSTS12P(8),OStarKim Chi - Normal,OStarKim Chi - Small,OStarNatural - Small,OStarPMai-TMuoi - Small,OStarS.W - Normal,OStarS.W - Small,SwingChicken - Small,SwingMAXX - Bo Small,SwingNYSteak - Normal,SwingNYSteak-Small S0005423 26 19.521 đơn Sản phẩm: C-PIE02P,C-PIE12P,CSTS12P(8),OStarKim Chi - Normal,OStarNatural - Small,OStarS.W - Normal,OStarS.W - Small,SwingNYSteak - Normal,SwingNYSteak-Small S0005423 26 19.522 đơn Sản phẩm: C-PIE02P,C-PIE12P,CSTS02P,CSTS06P,OStarKim Chi - Small,OStarNatural - Small,OStarPMai-TMuoi - Small,OStarS.W - Normal,SwingChicken - Small S0005423 26 19.523 đơn Sản phẩm: CSTS02P,CSTS06P,CSTS12P(8),OStarKim Chi - Small,OStarNatural - Small,OStarPMai-TMuoi - Small,OStarS.W - Small,SwingChicken - Small,SwingNYSteak-Small S0005423 26 19.524 đơn Sản phẩm: C-PIE02P,C-PIE12P,CSTS02P,CSTS06P,CSTS12P(8),OStarKim Chi - Small,OStarNatural - Small,OStarPMai-TMuoi - Small,OStarS.W - Small,SwingChicken - Small,SwingNYSteak-Small S0005423 26 19.525 đơn Sản phẩm: C-PIE02P,C-PIE12P,CSTS12P(8),OStarS.W - Small,SwingNYSteak-Small S0005423 26 19.526 đơn Sản phẩm: C-PIE02P,C-PIE12P
Em chưa lọc toàn bộ nhưng nếu liệt kê như vậy thì khả năng bỏ trùng tất cả các sku cho tất cả các trường hợp >75% đơn khả năng là sẽ ra tất cả các sku cuối cùngCode mình liệt kê tất cả các tổ hợp, nếu có 3 sp mua cùng sẽ liệt kê 4 trường hợp
Mình chưa hiểu ý của bạn "khả năng bỏ trùng tất cả các sku cho tất cả các trường hợp >75% đơn khả năng là sẽ ra tất cả các sku cuối cùng"Em chưa lọc toàn bộ nhưng nếu liệt kê như vậy thì khả năng bỏ trùng tất cả các sku cho tất cả các trường hợp >75% đơn khả năng là sẽ ra tất cả các sku cuối cùng
Ý em là ví dụ khách S0005360 thì có 4 sản phẩm mua cùng nhau là C-Pie12P, C-Pie06P, Csts12P(8), CSTS06P, còn kết quả file của anh là nó bị lặp như vầyMình chưa hiểu ý của bạn "khả năng bỏ trùng tất cả các sku cho tất cả các trường hợp >75% đơn khả năng là sẽ ra tất cả các sku cuối cùng"
Em có hiểu nội dung bài toán anh. Đây chỉ là một câu hỏi nhỏ trong một nhánh. Tức là với mỗi loại được lọc ra thì sẽ phân tích theo Brand và Sku đồng thời kết hợp với tốc độ mua hàng của người tiêu dùng thì sẽ kết hợp chọn chạy chương trình như thế nào cho từng thời điểm. Sẽ kết hợp 2 sku hay 3,4,5,... sku tùy vào nhãn hàng và đặc điểm thị trường đó ạ. Nó cũng bao gồm sự kết hợp với nhóm đối tượng khách hàng( khách hàng lớn thì chọn kết hợp như nào, khách hàng nhỏ thì chọn kết hợp như nào). Để chọn được lấy nhóm nào nó bao gồm tổ hợp( đơn hàng, sức mạnh nhãn hàng, tốc độ sử dụng của người tiêu dùng, đối tượng khách hàng, hiệu quả doanh thu). Cái em hỏi về Đơn hàng chỉ là một mục nhỏ trong đó thôi ạ! Chọn cái nào nó sẽ phụ thuộc vào chiến lược của các yếu tố khác.Vậy là bạn chưa lường hết nội dung bài toán.
Khi mình đưa ra giải thuật, bạn nghĩ đó là phức tạp, nhưng nó phải là như vậy vì thự tế là thế mà.
Bạn còn xét thêm:
* Số lượng mặt hàng trong nhóm đạt yêu cầu mua cùng nhau là nhiều nhất hay bằng bao nhiêu (2-3-4-5...mặt hàng).
* Các mặt hàng trong các nhóm đạt yêu cầu là không lặp lại.
* Trường hợp các nhóm 3 mặt hàng đạt số lần mua cùng nhau là 99%, nhóm 4 mặt hàng đạt số lần mua cùng nhau là 76%, thì chọn nhóm 3 hay nhóm 4?
Vậy mà bạn đăng vào mục "Hàm và công thức Excel", chắc nhiều bác nghĩ cách bằng công thức thì đến giờ vẫn chưa ra được.xin giải pháp Python hay ngôn ngữ khác.
Đúng là mình Post nhầm mục, nhờ anh chị Admin chuyển dùm em sang mục ngôn ngữ khác với ạ, em cảm ơn!Vậy mà bạn đăng vào mục "Hàm và công thức Excel", chắc nhiều bác nghĩ cách bằng công thức thì đến giờ vẫn chưa ra được.
Kết quả như vầy anh ạ:
Sản phẩm muốn được trích ra thì nó phải cùng nhau xuất hiện xuất hiện >75% số đơn là được, ví dụ khách hàng S0005360, tổng đơn là 26, 75% đơn là 19.5, tức là cứ xuất hiện cùng nhau 20 đơn trở lên là tách ra: Vậy sản phẩm tách ra là
Khách hàng Tổng đơn 75% đơn Số đơn Sản phẩm mua cùng 75% số Bill S0005360 26 19.520 đơn Sản phẩm: CSTS06P,CSTS12P(8) S0005360 26 19.521 đơn Sản phẩm: C-PIE06P,C-PIE12P,CSTS06P S0005360 26 19.522 đơn Sản phẩm: C-PIE06P,CSTS12P(8) S0005360 26 19.523 đơn Sản phẩm: C-PIE06P,C-PIE12P S0005360 26 19.524 đơn Sản phẩm: C-PIE12P,CSTS12P(8)
Được trích ra từ kết hợp của 20 đơn đến 24 đơn có các sản phẩm cùng nhau.
CSTS06P,CSTS12P(8),
C-PIE06P,C-PIE12P
Khách hàng và sản phẩm khác tương tự vậy
Bạn nói không rỏ nên Code mình liệt kê toàn bộ các trường hợp kết quả, để khi cần xử lý tiếp sẽ thuận tiện hơnÝ em là ví dụ khách S0005360 thì có 4 sản phẩm mua cùng nhau là C-Pie12P, C-Pie06P, Csts12P(8), CSTS06P, còn kết quả file của anh là nó bị lặp như vầy
View attachment 287064
Sau khi lấy duy nhất thì nó cũng là 4 mã C-Pie12P, C-Pie06P, Csts12P(8), CSTS06P đó ạ!
Em chưa hiểu cách duyệt lấy kết quả của code, mặc dù nó có lặp lại nhưng kết quả cuối cùng sau khi bỏ trùng lấy ra sản phẩm duy nhất thì chuẩn rồi anh.Bạn nói không rỏ nên Code mình liệt kê toàn bộ các trường hợp kết quả, để khi cần xử lý tiếp sẽ thuận tiện hơn
Cụ thể khách hàng S0005360 bạn muốn kết quả là gì?
Theo kết quả bạn ấy đưa thì bài này chỉ xét 2 cặp thôi sau group lại theo số đơnBạn nói không rỏ nên Code mình liệt kê toàn bộ các trường hợp kết quả, để khi cần xử lý tiếp sẽ thuận tiện hơn
Cụ thể khách hàng S0005360 bạn muốn kết quả là gì?
Bữa trước thấy bài của bạn rồi tính không giải, mà thấy có vẻ chưa xong nên tham gia chút cho vui. Mà Power BI nó rất mạnh ở xử lý (ETL) và phân tích chứ không riêng gì trực quan hóa, về công nghệ nó ngang với Analysis services mạnh hơn mấy thằng Relational database, nên dữ liệu vài chục trệu dòng Power BI mà chậm thì dùng Python SQL cũng chẳng khá hơn đâuTheo một cách logic như đã diễn giải thì có thể dùng Power Bi phân tích được, vấn đề phát sinh với dữ liệu lớn và hàng trăm sku, nếu nó chạy tổ hợp như vậy rất là nặng máy, nếu chạy 1,2 cái câu hỏi như vậy thì khả năng dẫn đến ngồi chơi xơi nước. Em vẫn nghĩ R hay Python sẽ mạnh hơn trong cái khoản phân tích này dù sao Power Bi chủ yếu mạnh mẽ ở phần trực quan hóa thôi. Em tìm kiếm giải pháp ngoài Power Bi
Cảm ơn anh nhiều nhé! Công nhận đoạn code Dax của anh chạy nhanh thật, em viết cũng ra nhưng chạy máy bàn 64gb ram mà vẫn mất 20s, chạy lapop ram thấp là quay quay mãi mới ra được. Do em chỉ biết chút Dax nên vẫn nghĩ Python sẽ nhanh hơn.Theo kết quả bạn ấy đưa thì bài này chỉ xét 2 cặp thôi sau group lại theo số đơn
Bữa trước thấy bài của bạn rồi tính không giải, mà thấy có vẻ chưa xong nên tham gia chút cho vui. Mà Power BI nó rất mạnh ở xử lý (ETL) và phân tích chứ không riêng gì trực quan hóa, về công nghệ nó ngang với Analysis services mạnh hơn mấy thằng Relational database, nên dữ liệu vài chục trệu dòng Power BI mà chậm thì dùng Python SQL cũng chẳng khá hơn đâu
Bài này tôi làm trên group Power BI cũng khá lâu rồi y chang bài bạn hỏi, như cái report bạn đưa thì dùng thằng nào làm cũng được kể cả excel (excel thì khá nặng), và Power BI nhanh nhất so với SQL, Python (Python sài thư viện dành cho machine learning sẽ nhanh hơn với dữ liệu lớn), Power BI tôi viết lại 3 cách 2 table và 1 measure, Python tôi viết 2 cách, cách 1 theo kết quả report của bạn , cách 2 dùng thư viện mlxtend trả vét cạn giống kêt của bạn HieuCD muốn ra kết quả của bạn thêm vài step (dùng max_len) nữa là được, Excel thì dùng công thức 365 nhưng nó rất nặng mặc dù đã tách ra rồi nên chỉ tham khảo thôi vì giờ excel nó có đầy đủ vòng lặp , đệ quy nên làm mấy bài này là được, cùng 1 thuật toán power BI mất 0.05s, Python 0.2s, Excel> 1 phútView attachment 287138View attachment 287137View attachment 287136
Thuật toán vét cạn là thế nào bạn nhỉ? Có thể nói cho tôi biết sơ lược cách làm được không?Theo kết quả bạn ấy đưa thì bài này chỉ xét 2 cặp thôi sau group lại theo số đơn
Bữa trước thấy bài của bạn rồi tính không giải, mà thấy có vẻ chưa xong nên tham gia chút cho vui. Mà Power BI nó rất mạnh ở xử lý (ETL) và phân tích chứ không riêng gì trực quan hóa, về công nghệ nó ngang với Analysis services mạnh hơn mấy thằng Relational database, nên dữ liệu vài chục trệu dòng Power BI mà chậm thì dùng Python SQL cũng chẳng khá hơn đâu
Bài này tôi làm trên group Power BI cũng khá lâu rồi y chang bài bạn hỏi, như cái report bạn đưa thì dùng thằng nào làm cũng được kể cả excel (excel thì khá nặng), và Power BI nhanh nhất so với SQL, Python (Python sài thư viện dành cho machine learning sẽ nhanh hơn với dữ liệu lớn), Power BI tôi viết lại 3 cách 2 table và 1 measure, Python tôi viết 2 cách, cách 1 theo kết quả report của bạn , cách 2 dùng thư viện mlxtend trả vét cạn giống kêt của bạn HieuCD muốn ra kết quả của bạn thêm vài step (dùng max_len) nữa là được, Excel thì dùng công thức 365 nhưng nó rất nặng mặc dù đã tách ra rồi nên chỉ tham khảo thôi vì giờ excel nó có đầy đủ vòng lặp , đệ quy nên làm mấy bài này là được, cùng 1 thuật toán power BI mất 0.05s, Python 0.2s, Excel> 1 phútView attachment 287138View attachment 287137View attachment 287136
Vét cạn có điều kiện thì tôi dùng thư viện Python, chứ dữ liệu nhiều vét cạn dùng vòng lặp thì không khả thi, ví dụ hình dưới tính tổ hợp 40 sản phẩm đã thỏa điều kiện thì lượng vòng lặp đã trên 1000 tỷ rồi, tôi dùng fpgrowth sử dụng thuật thuật toán FP-TreeThuật toán vét cạn là thế nào bạn nhỉ? Có thể nói cho tôi biết sơ lược cách làm được không?
Xin anh tham khảo all code Python để mọi người ham khảo với ạ !Vét cạn có điều kiện thì tôi dùng thư viện Python, chứ dữ liệu nhiều vét cạn dùng vòng lặp thì không khả thi, ví dụ hình dưới tính tổ hợp 40 sản phẩm đã thỏa điều kiện thì lượng vòng lặp đã trên 1000 tỷ rồi, tôi dùng fpgrowth sử dụng thuật thuật toán FP-TreeView attachment 287206
Bạn có thể tham khảo code R:Xin anh tham khảo all code Python để mọi người ham khảo với ạ !