plt.figure(figsize=(10, 6))
plt.scatter(safetystock_df['productCode'], safetystock_df['averageOrder'])
plt.xlabel('Product Code')
plt.ylabel('Average Order')
plt.title('Biểu đồ thể hiện lượng đặt hàng trung bình hàng tuần')
plt.show()
Hiển thị biểu đồ cho tồn kho an toàn
plt.figure(figsize=(10, 6))
plt.scatter(safetystock_df['productCode'], safetystock_df['safetyStock'])
plt.xlabel('Product Code')
plt.ylabel('Safety Stock')
plt.title('Biểu đồ thể hiện mức tồn kho an toàn')
plt.show()
Tạo biểu đồ so sánh các cột với mức tồn kho an toàn
ax.set_xlabel('Product Code')
ax.set_ylabel('Quantity')
ax.set_title('Biểu đồ thể hiện các sản phẩm có mức tồn kho thấp hơn mức tồn kho an toàn')
ax.set_xticks(x)
ax.set_xticklabels(product_codes, rotation=90)
ax.legend()
def add_labels(bars):
for bar in bars:
height = bar.get_height()
ax.annotate('{}'.format(height),
xy=(bar.get_x() + bar.get_width() / 2, height),
xytext=(0, 3),
textcoords="offset points",
ha='center', va='bottom')
ax.set_xlabel('Product Code')
ax.set_ylabel('Quantity')
ax.set_title('Biểu đồ thể hiện tồn kho và tồn kho an toàn của TOP 20')
ax.set_xticks(x)
ax.set_xticklabels(product_codes, rotation=90) # Xoay nhãn trục x cho dễ đọc
ax.legend()
Hiển thị giá trị trên các cột
def add_labels(bars):
for bar in bars:
height = bar.get_height()
ax.annotate('{}'.format(height),
xy=(bar.get_x() + bar.get_width() / 2, height),
xytext=(0, 3), # 3 points vertical offset
textcoords="offset points",
ha='center', va='bottom')
ax.set_xlabel('Product Code')
ax.set_ylabel('Quantity')
ax.set_title('Biểu dồ thể hiện mức tồn kho thấp hơn mức tồn kho an toàn ')
ax.set_xticks(x)
ax.set_xticklabels(product_codes, rotation=90) # Xoay nhãn trục x cho dễ đọc
ax.legend()
Hiển thị giá trị trên các cột
def add_labels(bars):
for bar in bars:
height = bar.get_height()
ax.annotate('{}'.format(height),
xy=(bar.get_x() + bar.get_width() / 2, height),
xytext=(0, 3),
textcoords="offset points",
ha='center', va='bottom')
add_labels(bars1)
add_labels(bars2)
Hiển thị biểu đồ
plt.tight_layout()
plt.show()
Lọc các sản phẩm dưới mức tồn kho an toàn từ DataFrame safetystock_df
if not duplicate_products.empty:
duplicate_products_str = ", ".join(duplicate_products.astype(str)) # Chuyển đổi giá trị thành chuỗi
print("Các sản phẩm trùng lặp là:", duplicate_products_str)
else:
print("Không có sản phẩm trùng lặp.")
ax.set_xlabel('Product Code')
ax.set_ylabel('Quantity To Order')
ax.set_title('Biểu đồ thể hiện số lượng cần nhập của các sản phẩm dưới mức tồn kho an toàn')
ax.set_xticks(x)
ax.set_xticklabels(product_codes, rotation=90)
ax.legend()
Hiển thị giá trị trên các thanh
def add_labels(bars):
for bar in bars:
height = bar.get_height()
ax.annotate('{}'.format(height),
xy=(bar.get_x() + bar.get_width() / 2, height),
xytext=(0, 3),
textcoords="offset points",
ha='center', va='bottom')
import pandas as pd import math import matplotlib.pyplot as plt import numpy as np
Đọc dữ liệu từ các tệp CSV
products_df = pd.read_csv("products.csv") orders_df = pd.read_csv("orders.csv") orderdetails_df = pd.read_csv("orderdetail.csv")
=================================================================================================
----------------------------------XÁC ĐỊNH MẶC HÀNG CẦN NHẬP LOẠI I ------------------------------
Sản phẩm có mức tồn kho thấp hơn mức tồn kho an toàn cần nhập mặt hàng này
để đảm bảo việc vận hành của cửa hàng
================================================================================================
Công thức tính tồn kho an toàn
Phương pháp độ lệch chuẩn với biến động về nhu cầu hàng hóa
Điểm Z Độ lệch chuẩn của nhu cầu Căn bậc hai của Thời gian giao hàng trung bình
----------------Tính nhu cầu trung bình cho 1 tuần => độ lệch chuẩn ----------------------------
Nhóm xác định chu kỳ phân tích là trong 1 tuần 7 ngày
Chuyển đổi cột 'orderDate' sang kiểu dữ liệu datetime
orders_df['orderDate'] = pd.to_datetime(orders_df['orderDate'])
Hợp nhất các bảng orders và orderdetail
merged_df = orders_df.merge(orderdetails_df, on='orderNumber')
Nhóm dữ liệu theo productCode và tuần, tính tổng số lượng đặt hàng
grouped_data = merged_df.groupby(["productCode", pd.Grouper(key='orderDate', freq='W')])["quantityOrdered"].sum().reset_index()
Tính giá trị trung bình đặt hàng cho mỗi nhóm
average_orders = grouped_data.groupby("productCode")["quantityOrdered"].mean().reset_index()
Hợp bảng products_df với average_orders theo productCode => safetystock_df
safetystock_df = pd.merge(products_df, average_orders, on="productCode", how="inner")
Rename column
safetystock_df.rename(columns={"quantityOrdered": "averageOrder"}, inplace=True)
-------------------------Tính toán độ lệch chuẩn nhu cầu-----------------------------------
Tính độ lệch chuẩn cho từng sản phẩm
standard_deviation_of_demand_per_product = grouped_data.groupby("productCode")["quantityOrdered"].std().reset_index()
Thêm một cột mới vào DataFrame để lưu trữ độ lệch chuẩn
safetystock_df["standardDeviation"] = standard_deviation_of_demand_per_product["quantityOrdered"]
=======================================
Thêm cột mới quantityInStock từ products_df vào DataFrame safetystock_df
safetystock_df = safetystock_df.merge(products_df[['productCode', 'quantityInStock']], how='left', on='productCode')
-----------------Thời gian giao hàng (giả định)------------------------
Giá trị trung bình được tính theo tuần nên mục này lead_time =7 => 1 (tuần)
lead_time = 7
-----------------Xác định mức xác định lượng hàng dự trữ an toàn-------------------------------
cần được giữ để đạt được mức dịch vụ mong muốn
Nhóm muốn mức dịch vụ mong muốn 95.05% nghĩa là 95.05% đơn hàng có thể được đáp ứng đầy đủ từ kho hàng.
Z = 1.65
Tạo DataFrame mới để lưu trữ mức tồn kho an toàn cho mỗi sản phẩm
safety_stock_data = []
Lặp qua từng sản phẩm để tính toán mức tồn kho an toàn tương ứng
for index, row in safetystock_df.iterrows(): product_code = row["productCode"] average_order = row["averageOrder"] standard_deviation = row["standardDeviation"]
Tạo DataFrame từ dữ liệu vừa tính toán được
safety_stock_df = pd.DataFrame(safety_stock_data)
Merge DataFrame safetystock_df với safety_stock_df để thêm cột 'safetyStock'
safetystock_df = pd.merge(safetystock_df, safety_stock_df[['productCode', 'safetyStock']], on='productCode', how='left')
Tạo một cột mới để lưu trữ thông tin về việc mức tồn kho hiện tại có thấp hơn mức tồn kho an toàn không
safetystock_df["belowSafetyStock"] = safetystock_df["quantityInStock_x"] < safetystock_df["safetyStock"]
Xuất kết quả ra file CSV mới
safetystock_df.to_csv('safetystock_df.csv', index=False)
Hiển thị biểu đồ của lượng đặt hàng trung bình
plt.figure(figsize=(10, 6)) plt.scatter(safetystock_df['productCode'], safetystock_df['averageOrder']) plt.xlabel('Product Code') plt.ylabel('Average Order') plt.title('Biểu đồ thể hiện lượng đặt hàng trung bình hàng tuần') plt.show()
Hiển thị biểu đồ cho tồn kho an toàn
plt.figure(figsize=(10, 6)) plt.scatter(safetystock_df['productCode'], safetystock_df['safetyStock']) plt.xlabel('Product Code') plt.ylabel('Safety Stock') plt.title('Biểu đồ thể hiện mức tồn kho an toàn') plt.show()
Tạo biểu đồ so sánh các cột với mức tồn kho an toàn
below_safety_stock_products = safetystock_df[safetystock_df["belowSafetyStock"]]
Chuẩn bị dữ liệu cho biểu đồ cột nhóm
product_codes = below_safety_stock_products['productCode'] quantity_in_stock = below_safety_stock_products['quantityInStock_x'] safety_stock = below_safety_stock_products['safetyStock']
x = np.arange(len(product_codes)) # vị trí cho các nhóm width = 0.35 # chiều rộng của mỗi thanh
fig, ax = plt.subplots(figsize=(12, 6)) bars1 = ax.bar(x - width/2, quantity_in_stock, width, label='Quantity In Stock', color='blue') bars2 = ax.bar(x + width/2, safety_stock, width, label='Safety Stock', color='orange')
ax.set_xlabel('Product Code') ax.set_ylabel('Quantity') ax.set_title('Biểu đồ thể hiện các sản phẩm có mức tồn kho thấp hơn mức tồn kho an toàn') ax.set_xticks(x) ax.set_xticklabels(product_codes, rotation=90) ax.legend()
def add_labels(bars): for bar in bars: height = bar.get_height() ax.annotate('{}'.format(height), xy=(bar.get_x() + bar.get_width() / 2, height), xytext=(0, 3), textcoords="offset points", ha='center', va='bottom')
add_labels(bars1) add_labels(bars2)
plt.tight_layout() plt.show()
=================================================================================================
----------------------------------XÁC ĐỊNH MẶC HÀNG CẦN NHẬP LOẠI II ------------------------------
Sản phẩm có mức tồn kho thấp hơn mức tồn kho an toàn cần nhập mặt hàng này
để đảm bảo việc vận hành của cửa hàng
================================================================================================
Công thức tính tồn kho an toàn
Phương pháp độ lệch chuẩn với biến động về nhu cầu hàng hóa
Điểm Z Độ lệch chuẩn của nhu cầu Căn bậc hai của Thời gian giao hàng trung bình
----------------Tính nhu cầu trung bình cho 1 tuần => độ lệch chuẩn ----------------------------
Nhóm xác định chu kỳ phân tích là trong 1 tuần 7 ngày
-------------------------Tính toán độ lệch chuẩn nhu cầu-----------------------------------
-----------------Thời gian giao hàng (giả định)------------------------
Giá trị trung bình được tính theo tuần nên mục này lead_time =7 => 1 (tuần)
lead_time = 7
-----------------Xác định mức xác định lượng hàng dự trữ an toàn-------------------------------
cần được giữ để đạt được mức dịch vụ mong muốn
Nhóm muốn mức dịch vụ mong muốn 99.00% nghĩa là 99.00% đơn hàng có thể được đáp ứng đầy đủ từ kho hàng.
Z2 = 2.326
Sắp xếp sản phẩm theo lượng đặt hàng trung bình hàng tuần từ cao đến thấp
top_products = average_orders.sort_values(by='quantityOrdered', ascending=False).head(20)
Lọc dữ liệu của top 20 sản phẩm từ grouped_data
top_grouped_data = grouped_data[grouped_data['productCode'].isin(top_products['productCode'])]
Tính standard_deviation cho top 20 sản phẩm
top_standard_deviation = top_grouped_data.groupby("productCode")["quantityOrdered"].std().reset_index()
Merge DataFrame products_df với top_products để chỉ lấy thông tin của top sản phẩm
top_products_df = pd.merge(products_df, top_products[['productCode', 'quantityOrdered']], on='productCode', how='inner')
Tính toán tồn kho an toàn cho các sản phẩm top
safety_stock_data_top = []
for index, row in top_products_df.iterrows(): product_code = row["productCode"] average_order = row["quantityOrdered"]
Tạo DataFrame từ dữ liệu vừa tính toán được
safetyStock2_df = pd.DataFrame(safety_stock_data_top)
Merge DataFrame products_df với safetyStock2_df để thêm cột 'safetyStock'
safetyStock2_df = pd.merge(top_products_df, safetyStock2_df[['productCode', 'safetyStock']], on='productCode', how='left')
Tạo một cột mới để lưu trữ thông tin về việc mức tồn kho hiện tại có thấp hơn mức tồn kho an toàn không
safetyStock2_df["belowSafetyStock"] = safetyStock2_df["quantityInStock"] < safetyStock2_df["safetyStock"]
Xuất kết quả ra file CSV mới
safetyStock2_df.to_csv('safetyStock2_df.csv', index=False)
Chuẩn bị dữ liệu
product_codes = safetyStock2_df['productCode'] quantity_in_stock = safetyStock2_df['quantityInStock'] safety_stock = safetyStock2_df['safetyStock']
Thiết lập vị trí cho các cột
x = np.arange(len(product_codes)) # vị trí cho các nhóm width = 0.35 # chiều rộng của mỗi cột
Vẽ biểu đồ cột
fig, ax = plt.subplots(figsize=(12, 6)) bars1 = ax.bar(x - width/2, quantity_in_stock, width, label='Quantity In Stock', color='blue') bars2 = ax.bar(x + width/2, safety_stock, width, label='Safety Stock', color='orange')
Thiết lập nhãn và tiêu đề
ax.set_xlabel('Product Code') ax.set_ylabel('Quantity') ax.set_title('Biểu đồ thể hiện tồn kho và tồn kho an toàn của TOP 20') ax.set_xticks(x) ax.set_xticklabels(product_codes, rotation=90) # Xoay nhãn trục x cho dễ đọc ax.legend()
Hiển thị giá trị trên các cột
def add_labels(bars): for bar in bars: height = bar.get_height() ax.annotate('{}'.format(height), xy=(bar.get_x() + bar.get_width() / 2, height), xytext=(0, 3), # 3 points vertical offset textcoords="offset points", ha='center', va='bottom')
add_labels(bars1) add_labels(bars2)
Hiển thị biểu đồ
plt.tight_layout() plt.show()
Lọc các sản phẩm dưới mức tồn kho an toàn
below_safety_stock_df = safetyStock2_df[safetyStock2_df["belowSafetyStock"]]
Biểu đồ thể hiện so sánh mức tồn kho so với mức tồn kho an toàn
Chuẩn bị dữ liệu cho biểu đồ cột
product_codes = below_safety_stock_df['productCode'] quantity_in_stock = below_safety_stock_df['quantityInStock'] safety_stock = below_safety_stock_df['safetyStock']
Thiết lập vị trí cho các cột
x = np.arange(len(product_codes)) # vị trí cho các nhóm width = 0.35 # chiều rộng của mỗi cột
Vẽ biểu đồ cột
fig, ax = plt.subplots(figsize=(12, 6)) bars1 = ax.bar(x - width/2, quantity_in_stock, width, label='Quantity In Stock', color='blue') bars2 = ax.bar(x + width/2, safety_stock, width, label='Safety Stock', color='orange')
Thiết lập nhãn và tiêu đề
ax.set_xlabel('Product Code') ax.set_ylabel('Quantity') ax.set_title('Biểu dồ thể hiện mức tồn kho thấp hơn mức tồn kho an toàn ') ax.set_xticks(x) ax.set_xticklabels(product_codes, rotation=90) # Xoay nhãn trục x cho dễ đọc ax.legend()
Hiển thị giá trị trên các cột
def add_labels(bars): for bar in bars: height = bar.get_height() ax.annotate('{}'.format(height), xy=(bar.get_x() + bar.get_width() / 2, height), xytext=(0, 3), textcoords="offset points", ha='center', va='bottom')
add_labels(bars1) add_labels(bars2)
Hiển thị biểu đồ
plt.tight_layout() plt.show()
Lọc các sản phẩm dưới mức tồn kho an toàn từ DataFrame safetystock_df
below_safety_stock_products_type1 = safetystock_df[safetystock_df["belowSafetyStock"]]
Lọc các sản phẩm dưới mức tồn kho an toàn từ DataFrame safetyStock2_df
below_safety_stock_products_type2 = safetyStock2_df[safetyStock2_df["belowSafetyStock"]]
Đưa ra số lượng từng sản phẩm dưới mức tồn kho an toàn của 2 loại dạng list
products_below_safety_stock_type1 = below_safety_stock_products_type1[['productCode', 'quantityInStock_x', 'safetyStock']] products_below_safety_stock_type2 = below_safety_stock_products_type2[['productCode', 'quantityInStock', 'safetyStock']]
Đổi tên các cột của products_below_safety_stock_type2 để đồng nhất với products_below_safety_stock_type1
products_below_safety_stock_type2 = products_below_safety_stock_type2.rename(columns={'quantityInStock': 'quantityInStock_x'})
Xác định các sản phẩm trùng lặp
duplicate_products = products_below_safety_stock_type1['productCode'][products_below_safety_stock_type1['productCode'].isin(products_below_safety_stock_type2['productCode'])]
Loại bỏ các sản phẩm từ loại 1 nếu chúng trùng với sản phẩm từ loại 2
products_below_safety_stock_type1 = products_below_safety_stock_type1[~products_below_safety_stock_type1['productCode'].isin(duplicate_products)]
Kết hợp cả hai loại sản phẩm dưới mức tồn kho an toàn vào một DataFrame
combined_products_below_safety_stock = pd.concat([products_below_safety_stock_type1, products_below_safety_stock_type2])
Tính số lượng cần nhập
combined_products_below_safety_stock['quantityToOrder'] = combined_products_below_safety_stock['safetyStock'] - combined_products_below_safety_stock['quantityInStock_x']
Lọc chỉ lấy cột productCode, safetyStock, và quantityToOrder
final_df = combined_products_below_safety_stock[['productCode', 'safetyStock', 'quantityToOrder']]
Loại bỏ các hàng có giá trị quantityToOrder âm hoặc bằng không
final_df = final_df[final_df['quantityToOrder'] > 0]
Hiển thị bảng kết quả
print(final_df.to_string(index=False))
Thông báo về các sản phẩm trùng lặp
if not duplicate_products.empty: duplicate_products_str = ", ".join(duplicate_products.astype(str)) # Chuyển đổi giá trị thành chuỗi print("Các sản phẩm trùng lặp là:", duplicate_products_str) else: print("Không có sản phẩm trùng lặp.")
Chuẩn bị dữ liệu cho biểu đồ
product_codes = final_df['productCode'] quantity_to_order = final_df['quantityToOrder']
Thiết lập vị trí cho các thanh
x = np.arange(len(product_codes)) width = 0.35
Vẽ biểu đồ cột
fig, ax = plt.subplots(figsize=(12, 6)) bars = ax.bar(x, quantity_to_order, width, label='Quantity To Order', color='green')
Thiết lập nhãn và tiêu đề
ax.set_xlabel('Product Code') ax.set_ylabel('Quantity To Order') ax.set_title('Biểu đồ thể hiện số lượng cần nhập của các sản phẩm dưới mức tồn kho an toàn') ax.set_xticks(x) ax.set_xticklabels(product_codes, rotation=90) ax.legend()
Hiển thị giá trị trên các thanh
def add_labels(bars): for bar in bars: height = bar.get_height() ax.annotate('{}'.format(height), xy=(bar.get_x() + bar.get_width() / 2, height), xytext=(0, 3), textcoords="offset points", ha='center', va='bottom')
add_labels(bars)
Hiển thị biểu đồ
plt.tight_layout() plt.show()