<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Vanshika</title>
    <description>The latest articles on DEV Community by Vanshika (@thinknest).</description>
    <link>https://dev.to/thinknest</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4028094%2F80d021ed-3b01-4765-bdd8-68bc344d61c2.png</url>
      <title>DEV Community: Vanshika</title>
      <link>https://dev.to/thinknest</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thinknest"/>
    <language>en</language>
    <item>
      <title>The Hardest Part Wasn't Machine Learning: Building Customer Segments from 541,000 Retail Transactions</title>
      <dc:creator>Vanshika</dc:creator>
      <pubDate>Tue, 14 Jul 2026 06:10:57 +0000</pubDate>
      <link>https://dev.to/thinknest/the-hardest-part-wasnt-machine-learning-building-customer-segments-from-541000-retail-585e</link>
      <guid>https://dev.to/thinknest/the-hardest-part-wasnt-machine-learning-building-customer-segments-from-541000-retail-585e</guid>
      <description>&lt;p&gt;&lt;strong&gt;Every business has customers. Very few truly understand them.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A customer who bought something yesterday should not be treated the same as someone who has not returned in two years. And sending the same marketing offer to a one-time buyer and a regular shopper usually does not make much sense.&lt;/p&gt;

&lt;p&gt;That was the idea behind this project.&lt;/p&gt;

&lt;p&gt;The question was simple:&lt;/p&gt;

&lt;p&gt;Can transaction data alone reveal useful customer groups that help businesses make better decisions?&lt;/p&gt;

&lt;p&gt;The answer was yes—but not because of machine learning alone. The hardest part was not building a clustering model. It was cleaning and shaping more than 541,000 retail transactions into something reliable enough to analyze. This project follows that process, from raw transaction data to customer segments built with Python, RFM Analysis, and K-Means Clustering.&lt;/p&gt;

&lt;p&gt;Understanding the Problem&lt;/p&gt;

&lt;p&gt;Businesses collect a huge amount of transaction data every day, but raw data by itself does not tell much of a story.&lt;/p&gt;

&lt;p&gt;Without understanding customer behavior, companies often:&lt;/p&gt;

&lt;p&gt;Send the same campaign to everyone.&lt;br&gt;
Miss customers who are about to stop buying.&lt;br&gt;
Waste effort on customers who are unlikely to return.&lt;br&gt;
Overlook their most valuable buyers.&lt;/p&gt;

&lt;p&gt;Instead of treating every customer the same, businesses need a way to group them based on how they actually behave.&lt;/p&gt;

&lt;p&gt;That became the goal of this project.&lt;/p&gt;

&lt;p&gt;Using historical retail transactions, the aim was to find customers with similar buying patterns and turn those patterns into insights that a marketing team could actually use.&lt;/p&gt;

&lt;p&gt;The Dataset&lt;/p&gt;

&lt;p&gt;The project uses the Online Retail II dataset from the UCI Machine Learning Repository. It contains transaction records from a UK-based online retailer.&lt;/p&gt;

&lt;p&gt;The dataset includes over 541,000 transaction records with fields such as:&lt;/p&gt;

&lt;p&gt;Invoice Number&lt;br&gt;
Product Description&lt;br&gt;
Quantity Purchased&lt;br&gt;
Invoice Date&lt;br&gt;
Unit Price&lt;br&gt;
Customer ID&lt;br&gt;
Country&lt;/p&gt;

&lt;p&gt;At first, it looked like the data was ready to go.&lt;/p&gt;

&lt;p&gt;It was not.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo1qh3i5pbh45pzgn57xb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo1qh3i5pbh45pzgn57xb.png" alt=" " width="800" height="316"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Real Projects Start with Cleaning, Not Modeling&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;One thing became clear very quickly:&lt;/p&gt;

&lt;p&gt;Machine learning is only as good as the data behind it.&lt;/p&gt;

&lt;p&gt;Before calculating a single metric or training a model, the dataset needed a lot of cleaning.&lt;/p&gt;

&lt;p&gt;A few issues stood out right away:&lt;/p&gt;

&lt;p&gt;Missing Customer IDs&lt;br&gt;
Cancelled invoices marked by invoice numbers starting with "C"&lt;br&gt;
Negative quantities from returned items&lt;br&gt;
Invalid or zero prices&lt;br&gt;
Duplicate records&lt;/p&gt;

&lt;p&gt;If these were left in the dataset, the customer behavior analysis would have been misleading.&lt;/p&gt;

&lt;p&gt;The rule was simple:&lt;/p&gt;

&lt;p&gt;If a transaction does not represent a real customer purchase, it should not be used for segmentation.&lt;/p&gt;

&lt;p&gt;Using Pandas, each issue was handled step by step before moving on to feature engineering.&lt;/p&gt;

&lt;p&gt;import pandas as pd&lt;/p&gt;

&lt;p&gt;retail = pd.read_excel("online_retail_II.xlsx")&lt;/p&gt;

&lt;p&gt;retail = retail.dropna(subset=["Customer ID"])&lt;br&gt;
retail = retail[~retail["Invoice"].astype(str).str.startswith("C")]&lt;br&gt;
retail = retail[(retail["Quantity"] &amp;gt; 0) &amp;amp; (retail["Price"] &amp;gt; 0)]&lt;br&gt;
retail = retail.drop_duplicates()&lt;/p&gt;

&lt;p&gt;The code looks small, but it made a big difference. Once the bad records were removed, the remaining data was much more trustworthy and much better suited for analysis.&lt;/p&gt;

&lt;p&gt;Turning Transactions into Customer Behavior&lt;/p&gt;

&lt;p&gt;A single purchase does not say much about a customer.&lt;/p&gt;

&lt;p&gt;Two people might each have one transaction, but one may have bought yesterday while the other bought two years ago. Those are very different customers.&lt;/p&gt;

&lt;p&gt;To make the data more useful, the project used RFM Analysis, a common customer segmentation method.&lt;/p&gt;

&lt;p&gt;RFM looks at customer behavior through three questions:&lt;/p&gt;

&lt;p&gt;Recency&lt;/p&gt;

&lt;p&gt;How recently did the customer make a purchase?&lt;/p&gt;

&lt;p&gt;Customers who bought recently are usually more engaged and more likely to come back.&lt;/p&gt;

&lt;p&gt;Frequency&lt;/p&gt;

&lt;p&gt;How often does the customer buy?&lt;/p&gt;

&lt;p&gt;Customers who purchase often usually have a stronger relationship with the business.&lt;/p&gt;

&lt;p&gt;Monetary Value&lt;/p&gt;

&lt;p&gt;How much has the customer spent?&lt;/p&gt;

&lt;p&gt;Customers who spend more often contribute a larger share of revenue.&lt;/p&gt;

&lt;p&gt;Together, these three values give a compact but useful picture of each customer’s buying behavior.&lt;/p&gt;

&lt;p&gt;The next step was to calculate these values for every customer.&lt;/p&gt;

&lt;p&gt;snapshot_date = retail["InvoiceDate"].max() + pd.Timedelta(days=1)&lt;/p&gt;

&lt;p&gt;rfm = retail.groupby("Customer ID").agg({&lt;br&gt;
    "InvoiceDate": lambda x: (snapshot_date - x.max()).days,&lt;br&gt;
    "Invoice": "nunique",&lt;br&gt;
    "TotalPrice": "sum"&lt;br&gt;
})&lt;/p&gt;

&lt;p&gt;rfm.columns = ["Recency", "Frequency", "Monetary"]&lt;/p&gt;

&lt;p&gt;Instead of looking at hundreds of thousands of transactions, the data was now organized at the customer level, with each row representing one customer’s behavior.&lt;/p&gt;

&lt;p&gt;That made the dataset much more useful for clustering.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F51xm4jvdf0leu1iyhpab.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F51xm4jvdf0leu1iyhpab.png" alt=" " width="695" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Distribution plots of Recency, Frequency, and Monetary values.&lt;/p&gt;

&lt;p&gt;Why K-Means?&lt;/p&gt;

&lt;p&gt;At this point, each customer was represented by three numerical features.&lt;/p&gt;

&lt;p&gt;The question was no longer how to calculate the metrics. It was how to find natural groups in the data.&lt;/p&gt;

&lt;p&gt;K-Means Clustering was a good fit because it is simple, fast, and works well when the goal is to group customers with similar characteristics.&lt;/p&gt;

&lt;p&gt;But before training the model, one important step was needed.&lt;/p&gt;

&lt;p&gt;The three RFM features were on very different scales.&lt;/p&gt;

&lt;p&gt;For example, Monetary values could range from a few pounds to several thousand, while Frequency values were much smaller.&lt;/p&gt;

&lt;p&gt;If the data was used as-is, Monetary would dominate the clustering process.&lt;/p&gt;

&lt;p&gt;To avoid that, the features were scaled using StandardScaler before fitting the K-Means model.&lt;/p&gt;

&lt;p&gt;Choosing the number of clusters also took some testing. The Elbow Method was used to find a reasonable balance between simplicity and useful segmentation instead of picking a number at random.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4ulw57ywlnpdqtmjax4y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4ulw57ywlnpdqtmjax4y.png" alt=" " width="713" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The clusters showed clear differences in customer behavior. Some customers bought often and spent a lot. Some had only purchased once. Others looked like they were becoming inactive.&lt;/p&gt;

&lt;p&gt;Instead of dealing with thousands of individual transactions, the business could now work with a few clear customer groups, each needing a different approach.&lt;/p&gt;

&lt;p&gt;For example, loyal customers could be rewarded with special offers, while customers who seemed to be drifting away could be targeted with retention campaigns before they stopped buying altogether.&lt;/p&gt;

&lt;p&gt;That was the point where the project stopped being just a machine learning exercise and started becoming something useful for the business.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Learned
&lt;/h2&gt;

&lt;p&gt;The hardest part of this project was not the model—it was cleaning and understanding the data. Once the transactions were prepared properly, the clustering made much more sense.&lt;/p&gt;

&lt;p&gt;I also learned that machine learning only matters when it leads to useful business decisions. In this case, customer segments can help identify loyal, inactive, and high-value customers.&lt;/p&gt;

&lt;p&gt;If I built this again, I would try more features, compare other clustering methods, and make the analysis interactive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Customer segmentation is about turning raw transaction data into decisions. With data cleaning, RFM analysis, and K-Means clustering, it becomes possible to find patterns that are hard to see manually.&lt;/p&gt;

&lt;p&gt;If this post makes you think, &lt;strong&gt;"I could do this too,"&lt;/strong&gt; then it has done its job.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;UCI Machine Learning Repository – Online Retail II Dataset&lt;/li&gt;
&lt;li&gt;Python (Pandas, NumPy, Scikit-learn)&lt;/li&gt;
&lt;li&gt;Matplotlib &amp;amp; Seaborn for visualization&lt;/li&gt;
&lt;li&gt;Power BI for interactive dashboard creation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thank you for reading!&lt;/p&gt;

</description>
      <category>python</category>
      <category>datascience</category>
      <category>powerbi</category>
      <category>machinelearning</category>
    </item>
  </channel>
</rss>
