avatarJulien Dimastromatteo, PhD

Free AI web copilot to create summaries, insights and extended knowledge, download it at here

9815

Abstract

lt.xticks(rotation=<span class="hljs-number">45</span>) plt.legend(title=<span class="hljs-string">'Crops'</span>, bbox_to_anchor=(<span class="hljs-number">1.05</span>, <span class="hljs-number">1</span>), loc=<span class="hljs-string">'upper left'</span>) plt.tight_layout() plt.show()</pre></div><p id="c814">Here is the render:</p><figure id="add8"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*kxE9cdsrSsFWixeX76caLQ.png"><figcaption>SCB Crops Render 1 | Image Credit: Author.</figcaption></figure><p id="5bd8">As you can tell, this is a convoluted graph. It is definitely too busy to get any insights from it. What can we do to make it more readable? Here are a few tips:</p><ol><li><b>Focus on Top/Bottom Performers</b>: Plot only the top or bottom N crops based on their total predicted sales. This can help to focus on either the best-performing or the crops needing more attention.</li><li><b>Aggregate Sales by Month</b>: Instead of weekly data points, you could aggregate sales predictions by month. This reduces the number of data points and may highlight broader trends more clearly.</li><li><b>Aggregate Sales by Crops</b>: Instead of individual crop data points, you could aggregate sales predictions by total of the five best perfomers. This reduces the number of data points and may highlight broader trends more clearly.</li><li><b>Separate Plots for Each Crop</b>: Create plots for each crop or a subset of crops. This approach allows for a detailed view per crop without the overlap seen in a single, comprehensive graph.</li><li><b>Use a Heatmap</b>: Represent the data in a heatmap, with crops on one axis, weeks (or months) on the other, and color intensity representing sales volume. This provides a quick visual reference to identify when sales are highest or lowest.</li><li><b>Interactive Visualization</b>: If feasible, an interactive tool where users can select which crops to display or highlight could be very useful for exploring the data without overwhelming the viewer all at once.</li></ol><p id="ced8">For our study case, let’s aggregate Sales by the five best performers with a smoothing of the line.</p><div id="184c"><pre><span class="hljs-comment"># To make the line smoother, we can use a higher-order polynomial or a spline interpolation</span> <span class="hljs-comment"># for plotting the weekly sales data. Let's use scipy's UnivariateSpline for a smoother line.</span>

<span class="hljs-keyword">from</span> scipy.interpolate <span class="hljs-keyword">import</span> UnivariateSpline <span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np <span class="hljs-comment"># Prepare the data for spline interpolation</span> x = weekly_sales_total[<span class="hljs-string">'WeekNumber'</span>] y = weekly_sales_total[<span class="hljs-string">'Units'</span>] <span class="hljs-comment"># Fit the spline</span> spl = UnivariateSpline(x, y) spl.set_smoothing_factor(<span class="hljs-number">500</span>) <span class="hljs-comment"># Adjust the smoothing factor to control the smoothness</span> <span class="hljs-comment"># Generate more points for a smoother curve</span> x_smooth = np.linspace(x.<span class="hljs-built_in">min</span>(), x.<span class="hljs-built_in">max</span>(), <span class="hljs-number">500</span>) y_smooth = spl(x_smooth) <span class="hljs-comment"># Plotting the smooth curve</span> plt.figure(figsize=(<span class="hljs-number">15</span>, <span class="hljs-number">7</span>)) plt.plot(x_smooth, y_smooth, label=<span class="hljs-string">'Smoothed Prediction'</span>, color=<span class="hljs-string">'blue'</span>) plt.scatter(x, y, color=<span class="hljs-string">'red'</span>, label=<span class="hljs-string">'Original Data'</span>) plt.title(<span class="hljs-string">'Smoothed Total Weekly Sales Stems Prediction for 2024'</span>) plt.xlabel(<span class="hljs-string">'Week Number'</span>) plt.ylabel(<span class="hljs-string">'Total Units Sold'</span>) plt.legend() plt.grid(<span class="hljs-literal">True</span>) plt.tight_layout() plt.show()</pre></div><p id="f341">Here is the render:</p><figure id="6437"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*6PGQYlzvIOeudglThWXK2w.png"><figcaption>SCB Crops Render 2| Image Credit: Author.</figcaption></figure><p id="b8bf">This is definitely a cleaner view. Sales peaks are appearing. But how does this correlate with the 5 best best performers?</p><div id="2026"><pre><span class="hljs-comment"># To smooth all lines, including those for the top 5 crops, we will apply the spline interpolation</span> <span class="hljs-comment"># individually to each crop's weekly sales data.</span> plt.figure(figsize=(<span class="hljs-number">15</span>, <span class="hljs-number">7</span>)) <span class="hljs-comment"># Plot the smoothed total weekly sales as the background</span> plt.plot(x_smooth, y_smooth, label=<span class="hljs-string">'Total Predicted Sales'</span>, color=<span class="hljs-string">'grey'</span>, alpha=<span class="hljs-number">0.5</span>) <span class="hljs-comment"># For each of the top 5 crops, apply spline interpolation and plot the smoothed line</span> <span class="hljs-keyword">for</span> crop <span class="hljs-keyword">in</span> top_5_crops: crop_data = top_crops_weekly_sales[top_crops_weekly_sales[<span class="hljs-string">'Crops'</span>] == crop] crop_x = crop_data[<span class="hljs-string">'WeekNumber'</span>] crop_y = crop_data[<span class="hljs-string">'Units'</span>] <span class="hljs-comment"># Fit the spline for each crop</span> spl_crop = UnivariateSpline(crop_x, crop_y) spl_crop.set_smoothing_factor(<span class="hljs-number">500</span>) <span class="hljs-comment"># Adjust the smoothing factor to control the smoothness for each crop</span>

<span class="hljs-comment"># Generate more points for a smoother curve</span>
x_smooth_crop = np.linspace(crop_x.<span class="hljs-built_in">min</span>(), crop_x.<span class="hljs-built_in">max</span>(), <span class="hljs-number">500</span>)
y_smooth_crop = spl_crop(x_smooth_crop)

<span class="hljs-comment"># Plot the smoothed crop sales</span>
plt.plot(x_smooth_crop, y_smooth_crop, label=crop)

plt.title(<span class="hljs-string">'Smoothed Lines for Top 5 Crops and Total Weekly Sales Stems Prediction for 2024'</span>) plt.xlabel(<span class="hljs-string">'Week Number'</span>) plt.ylabel(<span class="hljs-string">'Units Sold'</span>) plt.legend() plt.grid(<span class="hljs-literal">True</span>) plt.tight_layout() plt.show()</pre></div><p id="b7cc">Here is the render:</p><figure id="976d"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*ScKKL0G3UdBc35EtjtWGCw.png"><figcaption>SCB Crops Render 3| Image Credit: Author.</figcaption></figure><p id="164d">As much as I like this representation with smoothed lines looking like mountains, I want to see how this transfer to monthly sales.</p><div id="c46d"><pre><span class="hljs-comment"># To transform weeks into months and plot the sum of crops sold per month,</span> <span class="hljs-comment"># we'll first map the week numbers to months. We'll use an approximate mapping based on the week number.</span> <span class="hljs-comment"># Then, we'll aggregate sales data by month.</span> <span class="hljs-comment"># Approximate mapping of weeks to months, considering the data spans from W07 to W46</span> week_to_month_mapping = { <span class="hljs-string">'W07'</span>: <span class="hljs-string">'Feb'</span>, <span class="hljs-string">'W08'</span>: <span class="hljs-string">'Feb'</span>, <span class="hljs-string">'W09'</span>: <span class="hljs-string">'Feb'</span>, <span class="hljs-string">'W10'</span>: <span class="hljs-string">'Mar'</span>, <span class="hljs-string">'W11'</span>: <span class="hljs-string">'Mar'</span>, <span class="hljs-string">'W12'</span>: <span class="hljs-string">'Mar'</span>, <span class="hljs-string">'W13'</span>: <span class="hljs-string">'Mar'</span>, <span class="hljs-string">'W14'</span>: <span class="hljs-string">'Apr'</span>, <span class="hljs-string">'W15'</span>: <span class="hljs-string">'Apr'</span>, <span class="hljs-string">'W16'</span>: <span class="hljs-string">'Apr'</span>, <span class="hljs-string">'W17'</span>: <span class="hljs-string">'Apr'</span>, <span class="hljs-string">'W18'</span>: <span class="hljs-string">'May'</span>, <span class="hljs-string">'W19'</span>: <span class="hljs-string">'May'</span>, <span class="hljs-string">'W20'</span>: <span class="hljs-string">'May'</span>, <span class="hljs-string">'W21'</span>: <span class="hljs-string">'May'</span>, <span class="hljs-string">'W22'</span>: <span class="hljs-string">'Jun'</span>, <span class="hljs-string">'W23'</span>: <span class="hljs-string">'Jun'</span>, <span class="hljs-string">'W24'</span>: <span class="hljs-string">'Jun'</span>, <span class="hljs-string">'W25'</span>: <span class="hljs-string">'Jun'</span>, <span class="hljs-string">'W26'</span>: <span class="hljs-string">'Jul'</span>, <span class="hljs-string">'W27'</span>: <span class="hljs-string">'Jul'</span>, <span class="hljs-string">'W28'</span>: <span class="hljs-string">'Jul'</span>, <span class="hljs-string">'W29'</span>: <span class="hljs-string">'Jul'</span>, <span class="hljs-string">'W30'</span>: <span class="hljs-string">'Aug'</span>, <span class="hljs-string">'W31'</span>: <span class="hljs-string">'Aug'</span>, <span class="hljs-string">'W32'</span>: <span class="hljs-string">'Aug'</span>, <span class="hljs-string">'W33'</span>: <span class="hljs-string">'Aug'</span>, <span class="hljs-string">'W34'</span>: <span class="hljs-string">'Sep'</span>, <span class="hljs-string">'W35'</span>: <span class="hljs-string">'Sep'</span>, <span class="hljs-string">'

Options

W36'</span>: <span class="hljs-string">'Sep'</span>, <span class="hljs-string">'W37'</span>: <span class="hljs-string">'Sep'</span>, <span class="hljs-string">'W38'</span>: <span class="hljs-string">'Oct'</span>, <span class="hljs-string">'W39'</span>: <span class="hljs-string">'Oct'</span>, <span class="hljs-string">'W40'</span>: <span class="hljs-string">'Oct'</span>, <span class="hljs-string">'W41'</span>: <span class="hljs-string">'Oct'</span>, <span class="hljs-string">'W42'</span>: <span class="hljs-string">'Nov'</span>, <span class="hljs-string">'W43'</span>: <span class="hljs-string">'Nov'</span>, <span class="hljs-string">'W44'</span>: <span class="hljs-string">'Nov'</span>, <span class="hljs-string">'W45'</span>: <span class="hljs-string">'Nov'</span>, <span class="hljs-string">'W46'</span>: <span class="hljs-string">'Dec'</span> } <span class="hljs-comment"># Replace week columns with their corresponding month</span> data_filled_melted = data_filled.melt(id_vars=[<span class="hljs-string">"Crops"</span>], var_name=<span class="hljs-string">"Week"</span>, value_name=<span class="hljs-string">"Units"</span>) data_filled_melted[<span class="hljs-string">'Month'</span>] = data_filled_melted[<span class="hljs-string">'Week'</span>].<span class="hljs-built_in">map</span>(week_to_month_mapping) <span class="hljs-comment"># Aggregate sales data by month</span> monthly_sales = data_filled_melted.groupby(<span class="hljs-string">'Month'</span>)[<span class="hljs-string">'Units'</span>].<span class="hljs-built_in">sum</span>().reindex([<span class="hljs-string">'Feb'</span>, <span class="hljs-string">'Mar'</span>, <span class="hljs-string">'Apr'</span>, <span class="hljs-string">'May'</span>, <span class="hljs-string">'Jun'</span>, <span class="hljs-string">'Jul'</span>, <span class="hljs-string">'Aug'</span>, <span class="hljs-string">'Sep'</span>, <span class="hljs-string">'Oct'</span>, <span class="hljs-string">'Nov'</span>, <span class="hljs-string">'Dec'</span>]) <span class="hljs-comment"># Plotting the sum of crops sold per month</span> <span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt plt.figure(figsize=(<span class="hljs-number">10</span>, <span class="hljs-number">6</span>)) monthly_sales.plot(kind=<span class="hljs-string">'bar'</span>) plt.title(<span class="hljs-string">'Sum of Crops Sold Per Month'</span>) plt.xlabel(<span class="hljs-string">'Month'</span>) plt.ylabel(<span class="hljs-string">'Total Units Sold'</span>) plt.xticks(rotation=<span class="hljs-number">45</span>) plt.show()</pre></div><p id="f4b0">Here is the render:</p><figure id="3cf7"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*j_alWXKNgIPyanZqKlyRpA.png"><figcaption>SCB Crops Render 4| Image Credit: Author.</figcaption></figure><p id="1878">I like that. We definitely did not need that weekly granularity. Now, I’d like to how each of the crops contributes to the monthly total with some contrast and legend adjustments.</p><div id="2ab2"><pre><span class="hljs-comment"># Removing the "Month" label and the graph title, and replacing "Units Sold" with "Stems sold to florists".</span> plt.figure(figsize=(<span class="hljs-number">14</span>, <span class="hljs-number">8</span>)) <span class="hljs-comment"># Replotting without a title and with the updated y-axis label</span> monthly_sales_by_crop.plot(kind=<span class="hljs-string">'bar'</span>, stacked=<span class="hljs-literal">True</span>, colormap=<span class="hljs-string">'tab20'</span>, figsize=(<span class="hljs-number">14</span>, <span class="hljs-number">8</span>)) plt.xlabel(<span class="hljs-string">''</span>) <span class="hljs-comment"># Remove "Month" label</span> plt.ylabel(<span class="hljs-string">'Stems sold to florists'</span>) <span class="hljs-comment"># Update y-axis label</span> plt.xticks(rotation=<span class="hljs-number">45</span>) plt.tight_layout() <span class="hljs-comment"># Adjusting the legend to display horizontally below the graph</span> plt.legend(title=<span class="hljs-string">'Crops'</span>, bbox_to_anchor=(<span class="hljs-number">0.5</span>, -<span class="hljs-number">0.15</span>), loc=<span class="hljs-string">'upper center'</span>, ncol=<span class="hljs-number">4</span>) plt.show()</pre></div><p id="e536">Here is the final render:</p><figure id="f6e1"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/1*mMRiZ-_bWzWdfveJr3bqPA.png"><figcaption>SCB Crops Render 4| Image Credit: Author.</figcaption></figure><h2 id="630b">3. Analyze Data and Tell your Story</h2><ul><li><b>Identify Patterns:</b> Look for patterns in your sales history and customer preferences. Identify which flowers have consistent demand, which are growing in popularity, and which are declining.</li><li><b>Seasonal Variations:</b> Pay special attention to seasonal variations in demand. Certain flowers are more popular during specific seasons or holidays.</li><li><b>Capacity Analysis:</b> Assess your capacity to grow different types of flowers, considering space, climate, and resource availability</li></ul><h2 id="63bd">Data Storytelling</h2><p id="4248">The beginning of the year starts modestly, with February showing a limited but focused demand, primarily driven by early bloomers that cater to late winter and early spring floral needs.</p><p id="f36f">March sees a noticeable increase in diversity and volume, signaling the onset of spring. This is where we see a broader array of crops contributing to the sales mix, reflecting florists’ and their customers’ growing appetite for springtime colors and varieties.</p><p id="9a18">April and May underscore the peak of spring with a vibrant and robust sales volume. During these months, the diversity of flowers in demand is at its zenith, catering to a wide array of events and occasions, from weddings to Mother’s Day. The chart vividly illustrates the multitude of crops contributing to the sales, each color representing a different flower, painting a picture of a bustling floral market.</p><p id="b627">Transitioning into the summer months of June and July, there’s a slight shift in the composition of sales. While the volume remains high, certain crops dominate the sales chart, indicative of seasonal preferences and the changing availability of different flowers. The colors in the chart begin to stratify, showing clear leaders in the summer floral market.</p><p id="a8f0">August and September signal a gradual transition into the fall, with sales volumes beginning to ebb. However, it’s evident that certain crops, likely those that bloom beautifully into the late summer and early fall, maintain a strong presence in the market.</p><p id="4f9d">As the year progresses into October and November, the chart shows a tapering in volume, with a narrowed selection of crops making up the bulk of sales. This period likely reflects a market adjusting for the colder months, with florists and their customers gravitating towards flowers that can bring warmth and color to autumn and early winter settings.</p><h2 id="52dc">4. Choose Forecasting Methods</h2><p id="4d98">There are several forecasting methods you can use, depending on the complexity of your operations and the data available:</p><ul><li><b>Qualitative Methods:</b> If historical data is scarce, use qualitative methods like market research, expert opinions from florists, and customer surveys to forecast demand.</li><li><b>Quantitative Methods:</b> If you have sufficient historical sales data, apply quantitative methods such as:</li><li><b>Time Series Analysis:</b> Use this for forecasting based on historical sales trends, adjusting for seasonality, trends, and cycles.</li><li><b>Causal Models:</b> These models factor in causal relationships like economic indicators, market trends, and competitor actions that might affect demand.</li></ul><h2 id="2dc3">5. Develop Sales Forecasts</h2><ul><li><b>Create Demand Forecasts:</b> Based on your chosen method, forecast the demand for different flowers for the upcoming seasons or years.</li><li><b>Adjust for Uncertainty:</b> Incorporate a margin of error in your forecasts to account for unforeseen changes in market demand or supply chain disruptions.</li></ul><h2 id="846e">6. Plan Planting Schedules</h2><ul><li><b>Align Production with Demand:</b> Use your sales forecasts to plan what to plant, how much, and when. Ensure your planting schedules align with the forecasted demand, considering the growth cycle of each flower type.</li><li><b>Buffer Stocks:</b> Consider growing a small buffer stock of popular varieties to meet unexpected demand surges or to compensate for crop failures.</li></ul><h2 id="3813">7. Continuous Improvement</h2><ul><li><b>Monitor Performance:</b> Regularly compare actual sales against forecasts to understand discrepancies and refine your forecasting model.</li><li><b>Update Forecasts:</b> Continually update your forecasts with new sales data, customer feedback, and market trend information to improve accuracy.</li></ul><h2 id="26af">8. Leverage Technology</h2><ul><li><b>Software Solutions:</b> Consider using agricultural forecasting software or enterprise resource planning (ERP) systems designed for agriculture. These can help analyze data, forecast demand, and plan production more efficiently.</li></ul><h1 id="6bcc">Conclusion</h1><p id="fe8a">Sales forecasting and planning in flower farming is an ongoing process that requires attention to detail, flexibility, and responsiveness to market changes.</p><p id="e85d">By systematically analyzing data, choosing appropriate forecasting methods, and continuously refining your approach, you can better match your production with market demand, enhancing both your profitability and customer satisfaction.</p></article></body>

Data Storytelling with Python

How to Leverage Data Storytelling to Make Educated Business Decisions

Making educated decision that will impact positively the future of the company is not an easy job. Still, it is easier if you have collected data.

Photo by Markus Spiske on Unsplash

It seems tedious initially, but taking notes and collecting various data daily will make a huge difference in your company’s success. A month ago, I actively joined the field (literally and figuratively) of cut flower farming.

The farm is called “Spring Creek Blooms”. For three years, my life partner has grown and sold magnificent flowers to local florists, individuals in quest of happiness in their household, and brides and grooms who celebrate their unions.

As years passed, she got more and more inquiries. People love her flowers and the way she cares about them. With an environment-oriented mind, she was physically in the field planting, spraying, weeding, and harvesting all day. When she’s not in the field, I usually find her planning for the future in our office.

As glamorous as it sounds, we often romanticize the world of flower farming. Indeed, the end product is dreamy and full of colors, but the behind the scene is filled with challenges and nightmare. At least, it could be, especially when dealing with uncertainty or when dealing with things we can’t control. Believe me, farming is full of the latter.

That’s where my role becomes important. My role is to decrease the amount of uncertainty. How am I doing this? with DATA. Collecting a lot of data. Even data that does not seem useful to start with. I learned during my scientific career that too much data is better than not enough.

Indeed, when my partner was developing her company by herself, she always had in mind to collect a maximum of data. Still, the reality of her gigantesque enterprise prevented her from accomplishing the task.

“Here, I stand in the field, surveying the crops, crafting spreadsheets carefully.

There she sits, inscribing forms with the poetic names of flowers as we dispatch them to the florists.

Together, we devise plans for the future, guided by the tales told in our data entries.”

Planning for the future encompasses multiple facets, starting with a clear vision of our desired destination. Establishing our objective is a foundational step. Our primary aim is to boost our sales to ensure a sustainable livelihood.

This growth hinges on various elements, notably the volume of crops we can cultivate, which is limited by the square footage at our disposal. Equally critical is the market demand; an increase in sales is unattainable without a corresponding demand for our products.

How to Adapt Your Offer to the Market Demand

Photo by Christina @ wocintechchat.com on Unsplash

To adapt your flower farming offer to market demand, conduct thorough market research to identify trends and customer preferences and analyze competitor offerings.

Diversify your product range by introducing a variety of flowers, including unique and seasonal blooms, and consider value-added products like bouquets. Implement sustainable farming practices to appeal to eco-conscious consumers and differentiate your products in the market.

Finally, develop a strong marketing strategy, leveraging online platforms and direct sales channels while fostering business partnerships with florists and event planners to ensure your offerings efficiently meet current and future demands. I will elaborate on each these topic in a future post but for now, let’s focus on how to forecast your sales.

How to Forecast Your Sales

Photo by JESHOOTS.COM on Unsplash

Forecasting sales and planning your planting accordingly is a critical process for aligning your flower farming operations with market demand. This involves analyzing customer and florist feedback, historical sales data, market trends, and using forecasting models. Here’s a step-by-step guide to help you with this process.

1. Gather and Visualize your Data

In this case study, we will simplify our approach by focusing on a select range of data sources, given the history and operational context of your company. These include:

  • Customer Feedback: We’ll compile insights from customer feedback on their preferred flower varieties, sizes, colors, and other specific preferences.
  • Sales History: Our primary focus will be on analyzing the historical sales data from last year, which includes volumes sold, identification of seasonal trends, and growth rates across different types of flowers.
  • Market Trends: We will integrate knowledge of current market trends and seasonal demand variations, assuming these have influenced past sales.
  • Supply Chain Considerations: While considering the operational aspects, we’ll assume there were no significant supply chain issues, considering lead times for seeds or bulbs, growing cycles, and any potential production constraints.

This case study will primarily utilize the historical sales data collected last year. This decision is based on the assumption that these sales figures reflect market trends and customer preferences. Additionally, we assume that any relevant discussions with customers have already occurred and that the supply chain has been operating without disruptions.

We will use Python code to inspect and analyze our data as usual. Let’s first load and inspect the data.

  1. All our data are collected in Excel spreadsheets.
  2. Export the sheet to CSV file
  3. Import Panda library, load the CSV file, and display the data as a table as follow:
# Let's first load and inspect the uploaded CSV file to understand its structure and contents.
import pandas as pd
# Load the CSV file
file_path = '/mnt/data/Stems per crops.csv'
data = pd.read_csv(file_path)
# Display the first few rows of the dataframe to understand its structure and contents
data.head() 

Note that for privacy reason, the actual data table will not been shown. However, I can tell you that each column represent a week number (W06, W07, …) and each row represent the number of stems sold for each of the 39 crops.

2. Plot Data

We are now going to plot the data. 1. First, let’s import the appropriate libraries: matplotlib and seaborn.

# Plot the unit amount for each crop over the weeks
import matplotlib.pyplot as plt
import seaborn as sns
  • Let’ fill the missing values (# of stems sold) with 0.
# Fill missing values with 0 in the filtered data before melting for the plot
data_filtered_filled = data_filtered.fillna(0)
  • Plot the stems(units) amount for each crop over the weeks.
# Plot the stems amount for each crop over the weeks with missing values considered as 0
plt.figure(figsize=(18, 10))
sns.lineplot(data=data_melted_filled, x="Week", y="Units", hue="Crops", marker="o")
plt.title('Predicted Sales Units for Each Crop Over the Weeks (Missing Values as 0)')
plt.xlabel('Week')
plt.ylabel('Predicted Sales Units')
plt.xticks(rotation=45)
plt.legend(title='Crops', bbox_to_anchor=(1.05, 1), loc='upper left')
plt.tight_layout()
plt.show()

Here is the render:

SCB Crops Render 1 | Image Credit: Author.

As you can tell, this is a convoluted graph. It is definitely too busy to get any insights from it. What can we do to make it more readable? Here are a few tips:

  1. Focus on Top/Bottom Performers: Plot only the top or bottom N crops based on their total predicted sales. This can help to focus on either the best-performing or the crops needing more attention.
  2. Aggregate Sales by Month: Instead of weekly data points, you could aggregate sales predictions by month. This reduces the number of data points and may highlight broader trends more clearly.
  3. Aggregate Sales by Crops: Instead of individual crop data points, you could aggregate sales predictions by total of the five best perfomers. This reduces the number of data points and may highlight broader trends more clearly.
  4. Separate Plots for Each Crop: Create plots for each crop or a subset of crops. This approach allows for a detailed view per crop without the overlap seen in a single, comprehensive graph.
  5. Use a Heatmap: Represent the data in a heatmap, with crops on one axis, weeks (or months) on the other, and color intensity representing sales volume. This provides a quick visual reference to identify when sales are highest or lowest.
  6. Interactive Visualization: If feasible, an interactive tool where users can select which crops to display or highlight could be very useful for exploring the data without overwhelming the viewer all at once.

For our study case, let’s aggregate Sales by the five best performers with a smoothing of the line.

# To make the line smoother, we can use a higher-order polynomial or a spline interpolation
# for plotting the weekly sales data. Let's use scipy's UnivariateSpline for a smoother line.

from scipy.interpolate import UnivariateSpline
import numpy as np
# Prepare the data for spline interpolation
x = weekly_sales_total['WeekNumber']
y = weekly_sales_total['Units']
# Fit the spline
spl = UnivariateSpline(x, y)
spl.set_smoothing_factor(500)  # Adjust the smoothing factor to control the smoothness
# Generate more points for a smoother curve
x_smooth = np.linspace(x.min(), x.max(), 500)
y_smooth = spl(x_smooth)
# Plotting the smooth curve
plt.figure(figsize=(15, 7))
plt.plot(x_smooth, y_smooth, label='Smoothed Prediction', color='blue')
plt.scatter(x, y, color='red', label='Original Data')
plt.title('Smoothed Total Weekly Sales Stems Prediction for 2024')
plt.xlabel('Week Number')
plt.ylabel('Total Units Sold')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

Here is the render:

SCB Crops Render 2| Image Credit: Author.

This is definitely a cleaner view. Sales peaks are appearing. But how does this correlate with the 5 best best performers?

# To smooth all lines, including those for the top 5 crops, we will apply the spline interpolation
# individually to each crop's weekly sales data.
plt.figure(figsize=(15, 7))
# Plot the smoothed total weekly sales as the background
plt.plot(x_smooth, y_smooth, label='Total Predicted Sales', color='grey', alpha=0.5)
# For each of the top 5 crops, apply spline interpolation and plot the smoothed line
for crop in top_5_crops:
    crop_data = top_crops_weekly_sales[top_crops_weekly_sales['Crops'] == crop]
    crop_x = crop_data['WeekNumber']
    crop_y = crop_data['Units']
    # Fit the spline for each crop
    spl_crop = UnivariateSpline(crop_x, crop_y)
    spl_crop.set_smoothing_factor(500)  # Adjust the smoothing factor to control the smoothness for each crop
    
    # Generate more points for a smoother curve
    x_smooth_crop = np.linspace(crop_x.min(), crop_x.max(), 500)
    y_smooth_crop = spl_crop(x_smooth_crop)
    
    # Plot the smoothed crop sales
    plt.plot(x_smooth_crop, y_smooth_crop, label=crop)
plt.title('Smoothed Lines for Top 5 Crops and Total Weekly Sales Stems Prediction for 2024')
plt.xlabel('Week Number')
plt.ylabel('Units Sold')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

Here is the render:

SCB Crops Render 3| Image Credit: Author.

As much as I like this representation with smoothed lines looking like mountains, I want to see how this transfer to monthly sales.

# To transform weeks into months and plot the sum of crops sold per month,
# we'll first map the week numbers to months. We'll use an approximate mapping based on the week number.
# Then, we'll aggregate sales data by month.
# Approximate mapping of weeks to months, considering the data spans from W07 to W46
week_to_month_mapping = {
    'W07': 'Feb', 'W08': 'Feb', 'W09': 'Feb',
    'W10': 'Mar', 'W11': 'Mar', 'W12': 'Mar', 'W13': 'Mar',
    'W14': 'Apr', 'W15': 'Apr', 'W16': 'Apr', 'W17': 'Apr',
    'W18': 'May', 'W19': 'May', 'W20': 'May', 'W21': 'May',
    'W22': 'Jun', 'W23': 'Jun', 'W24': 'Jun', 'W25': 'Jun',
    'W26': 'Jul', 'W27': 'Jul', 'W28': 'Jul', 'W29': 'Jul',
    'W30': 'Aug', 'W31': 'Aug', 'W32': 'Aug', 'W33': 'Aug',
    'W34': 'Sep', 'W35': 'Sep', 'W36': 'Sep', 'W37': 'Sep',
    'W38': 'Oct', 'W39': 'Oct', 'W40': 'Oct', 'W41': 'Oct',
    'W42': 'Nov', 'W43': 'Nov', 'W44': 'Nov', 'W45': 'Nov', 'W46': 'Dec'
}
# Replace week columns with their corresponding month
data_filled_melted = data_filled.melt(id_vars=["Crops"], var_name="Week", value_name="Units")
data_filled_melted['Month'] = data_filled_melted['Week'].map(week_to_month_mapping)
# Aggregate sales data by month
monthly_sales = data_filled_melted.groupby('Month')['Units'].sum().reindex(['Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'])
# Plotting the sum of crops sold per month
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 6))
monthly_sales.plot(kind='bar')
plt.title('Sum of Crops Sold Per Month')
plt.xlabel('Month')
plt.ylabel('Total Units Sold')
plt.xticks(rotation=45)
plt.show()

Here is the render:

SCB Crops Render 4| Image Credit: Author.

I like that. We definitely did not need that weekly granularity. Now, I’d like to how each of the crops contributes to the monthly total with some contrast and legend adjustments.

# Removing the "Month" label and the graph title, and replacing "Units Sold" with "Stems sold to florists".
plt.figure(figsize=(14, 8))
# Replotting without a title and with the updated y-axis label
monthly_sales_by_crop.plot(kind='bar', stacked=True, colormap='tab20', figsize=(14, 8))
plt.xlabel('')  # Remove "Month" label
plt.ylabel('Stems sold to florists')  # Update y-axis label
plt.xticks(rotation=45)
plt.tight_layout()
# Adjusting the legend to display horizontally below the graph
plt.legend(title='Crops', bbox_to_anchor=(0.5, -0.15), loc='upper center', ncol=4)
plt.show()

Here is the final render:

SCB Crops Render 4| Image Credit: Author.

3. Analyze Data and Tell your Story

  • Identify Patterns: Look for patterns in your sales history and customer preferences. Identify which flowers have consistent demand, which are growing in popularity, and which are declining.
  • Seasonal Variations: Pay special attention to seasonal variations in demand. Certain flowers are more popular during specific seasons or holidays.
  • Capacity Analysis: Assess your capacity to grow different types of flowers, considering space, climate, and resource availability

Data Storytelling

The beginning of the year starts modestly, with February showing a limited but focused demand, primarily driven by early bloomers that cater to late winter and early spring floral needs.

March sees a noticeable increase in diversity and volume, signaling the onset of spring. This is where we see a broader array of crops contributing to the sales mix, reflecting florists’ and their customers’ growing appetite for springtime colors and varieties.

April and May underscore the peak of spring with a vibrant and robust sales volume. During these months, the diversity of flowers in demand is at its zenith, catering to a wide array of events and occasions, from weddings to Mother’s Day. The chart vividly illustrates the multitude of crops contributing to the sales, each color representing a different flower, painting a picture of a bustling floral market.

Transitioning into the summer months of June and July, there’s a slight shift in the composition of sales. While the volume remains high, certain crops dominate the sales chart, indicative of seasonal preferences and the changing availability of different flowers. The colors in the chart begin to stratify, showing clear leaders in the summer floral market.

August and September signal a gradual transition into the fall, with sales volumes beginning to ebb. However, it’s evident that certain crops, likely those that bloom beautifully into the late summer and early fall, maintain a strong presence in the market.

As the year progresses into October and November, the chart shows a tapering in volume, with a narrowed selection of crops making up the bulk of sales. This period likely reflects a market adjusting for the colder months, with florists and their customers gravitating towards flowers that can bring warmth and color to autumn and early winter settings.

4. Choose Forecasting Methods

There are several forecasting methods you can use, depending on the complexity of your operations and the data available:

  • Qualitative Methods: If historical data is scarce, use qualitative methods like market research, expert opinions from florists, and customer surveys to forecast demand.
  • Quantitative Methods: If you have sufficient historical sales data, apply quantitative methods such as:
  • Time Series Analysis: Use this for forecasting based on historical sales trends, adjusting for seasonality, trends, and cycles.
  • Causal Models: These models factor in causal relationships like economic indicators, market trends, and competitor actions that might affect demand.

5. Develop Sales Forecasts

  • Create Demand Forecasts: Based on your chosen method, forecast the demand for different flowers for the upcoming seasons or years.
  • Adjust for Uncertainty: Incorporate a margin of error in your forecasts to account for unforeseen changes in market demand or supply chain disruptions.

6. Plan Planting Schedules

  • Align Production with Demand: Use your sales forecasts to plan what to plant, how much, and when. Ensure your planting schedules align with the forecasted demand, considering the growth cycle of each flower type.
  • Buffer Stocks: Consider growing a small buffer stock of popular varieties to meet unexpected demand surges or to compensate for crop failures.

7. Continuous Improvement

  • Monitor Performance: Regularly compare actual sales against forecasts to understand discrepancies and refine your forecasting model.
  • Update Forecasts: Continually update your forecasts with new sales data, customer feedback, and market trend information to improve accuracy.

8. Leverage Technology

  • Software Solutions: Consider using agricultural forecasting software or enterprise resource planning (ERP) systems designed for agriculture. These can help analyze data, forecast demand, and plan production more efficiently.

Conclusion

Sales forecasting and planning in flower farming is an ongoing process that requires attention to detail, flexibility, and responsiveness to market changes.

By systematically analyzing data, choosing appropriate forecasting methods, and continuously refining your approach, you can better match your production with market demand, enhancing both your profitability and customer satisfaction.

Business
Python
Data Visualization
Storytelling
Data Science
Recommended from ReadMedium