Customer propensity to purchase

Background

Ecommerce ber-basis web merupakan suatu bidang yang sangat berkembang pesat. ecommerce websites sangat memudahkan proses belanja seroang costumer karena kita dapat membeli berbagai macam barang dimanapun kita berada. Banyak perusahaan besar yang telah berhasil membuat ecommerce website yang memiliki traffic yang sangat besar dan medapatkan revenue yang sangat baik. Banyak juga bisnis bisnis kecil yang turut serta membuat ecommerce website untuk meningkatkan pendapatan bisnis dan juga membuat produk mereka lebih terjangkau kesegala penjuru indonesia bahkan dunia.

costumer <- read.csv("data_input/training_sample.csv")
head(costumer)
  • UserID = Id dari setiap pengunjung
  • basket_icon click = Apakah pengunjung meng-klik shopping basket?
  • basket_add_list = Apakah pengunjung menambahkan produk ke shopping cart pada halaman list?
  • basket_add_detail = Did the visitor add a product to their shopping cart on the ‘detail’ page?
  • sort_by = Did the visitor sort products on a page?
  • image_picker = Did the visitor use the image picker?
  • account_page_click = Did the visitor visit their account page?
  • promo_banner_click = Did the visitor click on a promo banner?
  • detail_wishlist_add = Did the visitor add a product to their wishlist from the ‘detail’ page?
  • list_size_dropdown = Did the visitor interact with a product dropdown?
  • closed_minibasket_click = Did the visitor close their mini shopping basket?
  • checked_delivery_detail = Did the visitor view the delivery FAQ area on a product page?
  • checked_returns_detail = Did the visitor check the returns FAQ area on a product page?
  • sign_in = Did the visitor sign in to the website?
  • saw_checkout = Did the visitor view the checkout?
  • saw_sizecharts = Did the visitor view a product size chart?
  • saw_delivery = Did the visitor view the delivery FAQ page?
  • saw_account_upgrade = Did the visitor view the account upgrade page?
  • saw_homepage = Did the visitor view the website homepage?
  • device_mobile = Was the visitor on a mobile device?
  • device_computer = Was the visitor on a desktop device?
  • device_tablet = Was the visitor on a table device?
  • returning_user = Was the visitor new or returning?
  • loc_uk = Was the visitor located in the UK, based on their IP address?
  • ordered = Did the customer place an order?

Suatu website ecommerce harus dapat menarik dan meyakinkan costumer yang datang untuk melakukan transaksi. Perbedaan ecommerce dan belanja secara langsung di toko, kita kurang dapat melihat pelanggan mana yang sekiranya akan melakukan transaksi, alangkah baiknya jika mengetahui ciri-ciri pengunjung suatu ecommerce yang sekiranya akan melakukan transaksi sehingga kita dapat lebih meyakinkan pengunjung untuk membeli, seperti memberikan suati promo dan rekomendasi barang. Suatu ecommerce yang mendapatkan banyak pengunjung setiap hari, tetapi ecommerce tersebut tahu hanya sebagian kecil dari pengunjung yang cenderung melakukan transaksi, sementara sebagian besar mungkin bahkan tidak akan kembali. Saat ini Anda mungkin menghabiskan uang untuk memasarkan ulang kepada semua orang, tetapi mungkin kita dapat menggunakan pembelajaran mesin untuk mengidentifikasi prospek yang paling berharga?

Preprocessing data

Sebelum kita menganalis data, kita akan memeriksa apakah terdapat missing values didalam dataset.

colSums(is.na(costumer))
##                  UserID       basket_icon_click         basket_add_list 
##                       0                       0                       0 
##       basket_add_detail                 sort_by            image_picker 
##                       0                       0                       0 
##      account_page_click      promo_banner_click     detail_wishlist_add 
##                       0                       0                       0 
##      list_size_dropdown closed_minibasket_click checked_delivery_detail 
##                       0                       0                       0 
##  checked_returns_detail                 sign_in            saw_checkout 
##                       0                       0                       0 
##          saw_sizecharts            saw_delivery     saw_account_upgrade 
##                       0                       0                       0 
##            saw_homepage           device_mobile         device_computer 
##                       0                       0                       0 
##           device_tablet          returning_user                  loc_uk 
##                       0                       0                       0 
##                 ordered 
##                       0

Setelah kita cek tidak terdapat missing values didalam dataset, kita akan melihat tipe data dari variabel-variabel yang kita miliki, dan merubah tipe data yang belum sesuai.

glimpse(costumer)
## Rows: 455,401
## Columns: 25
## $ UserID                  <chr> "a720-6b732349-a720-4862-bd21-644732", "a0c...
## $ basket_icon_click       <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ basket_add_list         <int> 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ basket_add_detail       <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ sort_by                 <int> 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ image_picker            <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ account_page_click      <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ promo_banner_click      <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ detail_wishlist_add     <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ list_size_dropdown      <int> 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0...
## $ closed_minibasket_click <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ checked_delivery_detail <int> 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ checked_returns_detail  <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ sign_in                 <int> 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ saw_checkout            <int> 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ saw_sizecharts          <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ saw_delivery            <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ saw_account_upgrade     <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ saw_homepage            <int> 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1...
## $ device_mobile           <int> 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1...
## $ device_computer         <int> 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0...
## $ device_tablet           <int> 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ returning_user          <int> 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0...
## $ loc_uk                  <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1...
## $ ordered                 <int> 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...

Dapat kita lihat terdapat banyak tipe data integer yang seharusnya factor karena hanya memilki 2 level 0 dan 1, dan kita juga akan membuang costumer id karena variabel tersebut tidak berpengaruh kedalam model yang akan kita buat nanti.

costumer2 <- costumer %>% 
  select(-c(UserID)) %>% 
  mutate_if(is.integer, as.factor)

Selanjutnya kita melakukan pengecekan apakah terdapat class imbalance pada dataset costumer2:

prop.table(table(costumer2$ordered))
## 
##          0          1 
## 0.95807431 0.04192569

Ternyata terdapat class imbalance didalam dataset costumer2, makan untuk hasil yang lebih baik disini kita akan melakukan balancing menggunakan metode downsample pada train yang kita buat. Sebelum membuat model terlebih dahulu kita melakukan cross-validation terhadap data dengan mengambil proporsi 80% sebagai data training dan 20% sebagai data validation. Pembentukan sampel dengan menggunakan random sample.

RNGkind(sample.kind = "Rounding")
## Warning in RNGkind(sample.kind = "Rounding"): non-uniform 'Rounding' sampler
## used
set.seed(100)
intrain <- sample(nrow(costumer2), nrow(costumer2)*0.8)
costumer_train <- costumer2[intrain,]
costumer_test <- costumer2[-intrain,]

Melakukan downsample dengan proporsi 50:50.

costumer_train_down <- downSample(x = costumer_train %>% select(-ordered ),
                         y = as.factor(costumer_train$ordered ),
                         yname = "ordered ")
prop.table(table(costumer_train_down$ordered))
## 
##   0   1 
## 0.5 0.5

Dapat kita lihat proporsi variabel target yang kita miliki telah balance.

Data Exploration

Disini kita akan exploratory data menggunakan sankey diagram untuk memnujukan aliran dari satu variabel ke variabel lain.

costumer_1 <- costumer2 %>%
      mutate(ordered = ifelse(ordered == 0, "Not Ordered", "Ordered"),
          sign_in = ifelse(sign_in == 0, "Not Signed in", "Signed in"),
          basket_icon_click = ifelse(basket_icon_click == 0, "Not Click", "Click")) %>% 
   count(ordered, sign_in) %>% 
   rename(source=1,
          target=2)


costumer_2 <- costumer2 %>%
      mutate(ordered = ifelse(ordered == 0, "Not Ordered", "Ordered"),
          sign_in = ifelse(sign_in == 0, "Not Signed in", "Signed in"),
          basket_icon_click = ifelse(basket_icon_click == 0, "Not Click", "Click")) %>% 
   count(ordered, sign_in, basket_icon_click,name = "value")
   
costumer_3 <- costumer_1 %>% 
   left_join(costumer_2, by = c("source" = "ordered", "target"= "sign_in")) %>% 
   select(target, basket_icon_click, value) %>% 
   rename(source =target,
          target = 2,
          n= value)

costumer_final <- costumer_1 %>% 
   bind_rows(costumer_3)

node <- data.frame(name=c(costumer_final$source, costumer_final$target) %>% unique())

costumer_viz <- costumer_final %>% 
   mutate(
      idsource = match(.$source, node$name)-1,
      idtarget = match(.$target, node$name)-1
   )


sankeyNetwork(Links = costumer_viz, Nodes = node,
              Source = "idsource", Target = "idtarget",
              Value = "n", NodeID = "name")

Dapat dilihat pada plot diatas bahwa sebagian besar costumer tidak melakukan ordered dan yang sebaigan besar yang tidak ordered tidak melakukan sign in ke website dan tidak menambahkan item kedalam keranjang. Dan dapat dilihat juga costumer yang melakukan ordered dan sign in ke website ada juga yang tidak menambahkan item kedalam keranjang dan langsung membeli barang.

costumer_4 <- costumer2 %>%
      mutate(ordered = ifelse(ordered == 0, "Not Ordered", "Ordered"),
          returning_user = ifelse(returning_user == 0, "Not Return", "return"),
          promo_banner_click = ifelse(promo_banner_click == 0, "Not Click", "Click")) %>% 
   count(ordered, returning_user) %>% 
   rename(source=1,
          target=2)


costumer_5 <- costumer2 %>%
      mutate(ordered = ifelse(ordered == 0, "Not Ordered", "Ordered"),
          returning_user = ifelse(returning_user == 0, "Not Return", "return"),
          promo_banner_click = ifelse(promo_banner_click == 0, "Not Click", "Click")) %>% 
   count(ordered, returning_user, promo_banner_click, name = "value")
   
costumer_6 <- costumer_4 %>% 
   left_join(costumer_5, by = c("source" = "ordered", "target"= "returning_user")) %>% 
   select(target, promo_banner_click, value) %>% 
   rename(source =target,
          target = 2,
          n= value)

costumer_final2 <- costumer_4 %>% 
   bind_rows(costumer_6)

node2 <- data.frame(name=c(costumer_final2$source, costumer_final2$target) %>% unique())

costumer_viz2 <- costumer_final2 %>% 
   mutate(
      idsource = match(.$source, node2$name)-1,
      idtarget = match(.$target, node2$name)-1
   )


sankeyNetwork(Links = costumer_viz2, Nodes = node2,
              Source = "idsource", Target = "idtarget",
              Value = "n", NodeID = "name")

Dapat dilihat terdapat pelanggan yang melakukan order tapi dia bukan pelanggan yang kembali tetapi dia juga mengclick banner promo yang ada di web, dapat kita ambil kesimpulan adanya pengunjung web yang baru pertama kali masuk kedalam web kita dan melihat banner promo yang ada di halam utama sehinnga mambuat costumer tertarik untuk melakukan suatu transaksi