【运营数据分析-进阶篇】 商品与库存分析
6.1 商品销售分析
【理论讲解】
商品销售分析是电商运营的核心。通过分析商品的销售额、销量、毛利率、品类表现以及商品之间的关联性,我们可以优化商品结构、制定定价策略、捆绑销售和交叉销售,从而提升整体销售业绩。
核心指标:
- 销售额 (Revenue):
价格 * 数量 - 销量 (Volume): 售出的商品数量
- 毛利率 (Gross Margin):
(销售额-成本) / 销售额 - 品类表现: 不同品类的销售贡献
- 商品关联: 哪些商品经常一起被购买(“啤酒与尿布”效应)
【自动生成数据集与代码实例】
我们将生成包含订单、商品信息和成本价的模拟数据集。
python
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
import seaborn as sns
# --- 数据集生成 ---
np.random.seed(42)
def generate_product_sales_data(num_orders=5000, start_date='2023-01-01', end_date='2023-03-31'):
users = [f'U{i:04d}' for i in range(500)]
# 模拟商品信息 (包含成本价)
products_info = {}
product_categories = ['Electronics', 'Apparel', 'Home', 'Books', 'Sports']
product_brands = ['BrandA', 'BrandB', 'BrandC', 'BrandD', 'BrandE']
for i in range(100): # 100个商品
pid = f'P{i:03d}'
category = np.random.choice(product_categories, p=[0.25, 0.25, 0.2, 0.15, 0.15]) # 模拟不同品类热度
brand = np.random.choice(product_brands)
price = round(np.random.uniform(20, 1000), 2)
cost_price = round(price * np.random.uniform(0.3, 0.8), 2) # 成本价是售价的30%-80%
products_info[pid] = {'category': category, 'brand': brand, 'price': price, 'cost_price': cost_price}
product_ids = list(products_info.keys())
order_items_data = []
for i in range(num_orders):
order_id = f'ORD{i:05d}'
user_id = np.random.choice(users)
order_time = pd.to_datetime(start_date) + timedelta(seconds=np.random.randint(0, (pd.to_datetime(end_date) - pd.to_datetime(start_date)).total_seconds()))
num_items_in_order = np.random.randint(1, 4) # 每个订单1-3件商品
for _ in range(num_items_in_order):
product_id = np.random.choice(product_ids)
quantity = np.random.randint(1, 3)
# 从 products_info 获取价格和成本价
price = products_info[product_id]['price']
cost_price = products_info[product_id]['cost_price']
category = products_info[product_id]['category']
brand = products_info[product_id]['brand']
order_items_data.append([order_id, user_id, order_time, product_id, category, brand, price, cost_price, quantity])
df_sales = pd.DataFrame(order_items_data, columns=['order_id', 'user_id', 'order_time', 'product_id', 'category', 'brand', 'price', 'cost_price', 'quantity'])
df_sales['order_time'] = pd.to_datetime(df_sales['order_time'])
df_sales['total_revenue'] = df_sales['price'] * df_sales['quantity']
df_sales['total_cost'] = df_sales['cost_price'] * df_sales['quantity']
df_sales['gross_profit'] = df_sales['total_revenue'] - df_sales['total_cost']
return df_sales
df_sales_analysis = generate_product_sales_data(num_orders=5000)
print("--- 商品销售数据预览 ---")
print(df_sales_analysis.head())
# --- 商品销售额、销售量、毛利率计算 ---
print("\n--- 商品销售额、销售量、毛利率计算 ---")
# 1. 总销售额、总销量、总毛利
total_revenue = df_sales_analysis['total_revenue'].sum()
total_quantity_sold = df_sales_analysis['quantity'].sum()
total_gross_profit = df_sales_analysis['gross_profit'].sum()
overall_gross_margin = (total_gross_profit / total_revenue) if total_revenue > 0 else 0
print(f"总销售额: {total_revenue:.2f}")
print(f"总销量: {total_quantity_sold}")
print(f"总毛利: {total_gross_profit:.2f}")
print(f"整体毛利率: {overall_gross_margin:.2%}")
# 2. 按商品维度计算
product_performance = df_sales_analysis.groupby('product_id').agg(
total_sales=('total_revenue', 'sum'),
total_quantity=('quantity', 'sum'),
total_profit=('gross_profit', 'sum'),
avg_price=('price', 'mean')
).reset_index()
product_performance['gross_margin'] = (product_performance['total_profit'] / product_performance['total_sales']).fillna(0)
print("\n商品维度销售表现 (Top 5):\n", product_performance.sort_values(by='total_sales', ascending=False).head())
# 3. 按品类维度计算
category_performance = df_sales_analysis.groupby('category').agg(
total_sales=('total_revenue', 'sum'),
total_quantity=('quantity', 'sum'),
total_profit=('gross_profit', 'sum')
).reset_index()
category_performance['gross_margin'] = (category_performance['total_profit'] / category_performance['total_sales']).fillna(0)
print("\n品类维度销售表现 (Top 3):\n", category_performance.sort_values(by='total_sales', ascending=False).head(3))
# 可视化品类销售额贡献
plt.figure(figsize=(10, 6))
sns.barplot(x='category', y='total_sales', data=category_performance.sort_values(by='total_sales', ascending=False))
plt.title('各商品类别销售额贡献')
plt.xlabel('商品类别')
plt.ylabel('销售额')
plt.show()
# --- 商品关联分析 (Apriori算法入门) ---
print("\n--- 商品关联分析 ---")
# 目标:发现哪些商品经常一起被购买
# 1. 准备数据:将每个订单的商品列表转换为列表
orders_products = df_sales_analysis.groupby('order_id')['product_id'].apply(list).reset_index()
transactions = orders_products['product_id'].tolist()
print("\n前5个订单的商品列表:\n", transactions[:5])
# 2. 使用mlxtend库进行Apriori算法 (需要安装: pip install mlxtend)
from mlxtend.preprocessing import TransactionEncoder
from mlxtend.frequent_patterns import apriori, association_rules
# 将交易数据转换为One-Hot编码格式
te = TransactionEncoder()
te_ary = te.fit(transactions).transform(transactions)
df_transactions = pd.DataFrame(te_ary, columns=te.columns_)
# 查找频繁项集 (支持度 support)
# support: 某个商品组合在所有订单中出现的频率
frequent_itemsets = apriori(df_transactions, min_support=0.01, use_colnames=True) # 至少在1%的订单中出现
print("\n频繁项集 (Top 5):\n", frequent_itemsets.sort_values(by='support', ascending=False).head())
# 生成关联规则 (置信度 confidence, 提升度 lift)
# confidence(A->B): 买了A商品后,再买B商品的概率
# lift(A->B): 买了A商品后,买B商品的概率与单独买B商品的概率之比。>1表示正相关
rules = association_rules(frequent_itemsets, metric="lift", min_threshold=1) # lift > 1表示有正相关
rules = rules.sort_values(by=['lift', 'confidence'], ascending=[False, False])
print("\n关联规则 (Top 5):\n", rules.head())
# 【运营策略建议】
print("\n--- 基于商品销售分析的运营策略建议 ---")
print("1. **优化商品结构:** 根据品类贡献调整采购和推广重心。")
print("2. **捆绑销售/交叉销售:** 利用关联规则,将经常一起购买的商品进行捆绑销售或在商品详情页推荐。")
print("3. **新品推广:** 结合畅销品类和关联规则,设计新品推广方案。")
print("4. **滞销品处理:** 识别滞销品(销量低),分析原因并制定清仓策略。")
【互动问答】
- 毛利率对电商运营决策有什么重要意义?
- 如何根据商品销售数据识别出“爆款”商品和“滞销”商品?
- Apriori算法中的“支持度”、“置信度”、“提升度”分别代表什么?它们在商品关联分析中有什么作用?
- 在电商场景中,商品关联规则可以应用在哪些地方?(例如:购物车推荐、详情页推荐、套餐组合)
- 如果频繁项集太多,
min_support应该如何调整?
6.2 库存管理与优化
【理论讲解】
库存管理是电商成本控制和客户满意度的关键环节。过多的库存会占用资金、增加仓储成本,过少的库存则可能导致缺货,影响销售和用户体验。通过数据分析,我们可以更科学地预测需求、设置安全库存、识别滞销品,从而优化库存周转。
核心指标:
- 库存周转率: 衡量库存销售的速度。
- 安全库存: 为应对不确定性(如需求波动、供货延迟)而额外储备的库存量。
- 滞销率: 滞销商品占总商品数的比例。
- 缺货率: 因缺货而损失的销售机会比例。
【自动生成数据集与代码实例】
我们将生成包含库存、销售历史和预测需求的数据。
python
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
import seaborn as sns
# --- 数据集生成 ---
np.random.seed(42)
def generate_inventory_data(num_products=100, start_date='2023-01-01', end_date='2023-03-31'):
products_info = {}
product_categories = ['Electronics', 'Apparel', 'Home', 'Books', 'Sports']
inventory_data = []
for i in range(num_products):
pid = f'P{i:03d}'
category = np.random.choice(product_categories)
initial_stock = np.random.randint(50, 500) # 初始库存
lead_time = np.random.randint(3, 15) # 供货周期,天
std_demand = np.random.uniform(5, 20) # 每日需求标准差
# 模拟每日销售数据
current_stock = initial_stock
daily_sales_data = []
current_date = pd.to_datetime(start_date)
while current_date <= pd.to_datetime(end_date):
# 模拟每日需求量 (正态分布,有波动)
demand = max(0, int(np.random.normal(initial_stock / ((pd.to_datetime(end_date) - pd.to_datetime(start_date)).days / 20), std_demand))) # 确保需求量为正
# 模拟实际销售 (不能超过库存)
sales = min(demand, current_stock)
current_stock -= sales
daily_sales_data.append([pid, current_date, sales, current_stock])
# 模拟补货 (当库存低于某个阈值时)
if current_stock < 0.2 * initial_stock and np.random.rand() < 0.5: # 20%初始库存以下且50%概率补货
replenishment_quantity = np.random.randint(50, 200)
current_stock += replenishment_quantity
current_date += timedelta(days=1)
# 将每日销售数据添加到总库存数据中
for row in daily_sales_data:
inventory_data.append([row[0], category, products_info.get(row[0], {'price': 0}).get('price'), initial_stock, lead_time, std_demand, row[1], row[2], row[3]])
df_inventory = pd.DataFrame(inventory_data, columns=['product_id', 'category', 'price', 'initial_stock', 'lead_time', 'std_demand', 'date', 'daily_sales', 'current_stock'])
df_inventory['date'] = pd.to_datetime(df_inventory['date'])
return df_inventory
df_inventory_analysis = generate_inventory_data(num_products=50)
print("--- 库存数据预览 ---")
print(df_inventory_analysis.head())
# --- 安全库存量计算 ---
print("\n--- 安全库存量计算 ---")
# 假设我们关注过去30天的平均日销量和标准差
lookback_days = 30
df_inventory_analysis['rolling_avg_sales'] = df_inventory_analysis.groupby('product_id')['daily_sales'].transform(lambda x: x.rolling(window=lookback_days).mean())
df_inventory_analysis['rolling_std_sales'] = df_inventory_analysis.groupby('product_id')['daily_sales'].transform(lambda x: x.rolling(window=lookback_days).std())
# 仅保留最近的数据进行计算
latest_inventory_data = df_inventory_analysis.sort_values(by='date').groupby('product_id').tail(1).copy()
# 安全系数 Z (通常取1.65代表95%服务水平,1.96代表97.5%服务水平)
Z = 1.65 # 95%服务水平
# 安全库存公式: 安全库存 = Z * (日需求标准差) * sqrt(供货周期)
latest_inventory_data['safety_stock'] = (Z * latest_inventory_data['rolling_std_sales'] * np.sqrt(latest_inventory_data['lead_time'])).fillna(0).astype(int)
# 订货点公式: 订货点 = (平均日需求 * 供货周期) + 安全库存
latest_inventory_data['reorder_point'] = (latest_inventory_data['rolling_avg_sales'] * latest_inventory_data['lead_time'] + latest_inventory_data['safety_stock']).fillna(0).astype(int)
print("\n各商品的安全库存与订货点:\n", latest_inventory_data[['product_id', 'rolling_avg_sales', 'rolling_std_sales', 'lead_time', 'safety_stock', 'reorder_point', 'current_stock']].head())
# --- 滞销商品识别与处理 ---
print("\n--- 滞销商品识别与处理 ---")
# 滞销定义:例如,过去90天内销量为0的商品
df_sales_last_90_days = df_inventory_analysis[df_inventory_analysis['date'] >= (current_date - timedelta(days=90))]
product_sales_last_90_days = df_sales_last_90_days.groupby('product_id')['daily_sales'].sum().reset_index(name='total_sales_90_days')
# 找出没有销售记录的商品
all_products = df_inventory_analysis['product_id'].unique()
products_with_sales = product_sales_last_90_days[product_sales_last_90_days['total_sales_90_days'] > 0]['product_id']
dead_stock_products = pd.DataFrame({'product_id': list(set(all_products) - set(products_with_sales))})
print("\n滞销商品ID:\n", dead_stock_products)
# 【运营策略建议】
print("\n--- 基于库存分析的运营策略建议 ---")
print("1. **动态调整库存:** 根据安全库存和订货点,及时进行补货,避免缺货或积压。")
print("2. **滞销品清仓:** 对滞销商品进行促销、捆绑销售或降价清仓,减少库存成本。")
print("3. **缺货预警:** 监控当前库存与订货点的关系,提前预警并紧急补货。")
【互动问答】
- 安全库存和订货点在库存管理中的作用是什么?
- 如何选择合适的安全系数Z?它与服务水平有什么关系?
- 除了“过去90天销量为0”,你还能想到哪些方法来定义“滞销商品”?
- 如何评估库存管理的效果?(例如:库存周转率、缺货率)
- 在实际电商运营中,库存数据还会受到哪些因素的影响?如何将这些因素纳入分析?
6.3 价格敏感性分析
【理论讲解】
价格敏感性分析旨在了解消费者对商品价格变化的反应。通过分析不同价格区间的销售表现,以及促销活动对销量的影响,可以帮助我们制定更科学的定价策略和促销方案。
核心思想:
- 需求弹性: 商品价格变化百分比与需求量变化百分比的比率。
- 价格区间: 了解在不同价格点下,商品的销售情况。
- 促销效果: 评估价格折扣、满减等促销手段对销售的刺激作用。
【自动生成数据集与代码实例】
我们将生成包含商品价格、销售量以及是否进行促销的模拟数据。
python
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# --- 数据集生成 ---
np.random.seed(42)
def generate_price_sensitivity_data(num_products=50, num_days=90):
data = []
for i in range(num_products):
pid = f'P{i:03d}'
base_price = round(np.random.uniform(50, 500), 2)
for day in range(num_days):
current_date = pd.to_datetime('2023-01-01') + timedelta(days=day)
# 模拟价格波动 (在基础价格上下浮动)
price_factor = np.random.uniform(0.9, 1.1)
current_price = round(base_price * price_factor, 2)
# 模拟促销活动 (随机进行促销)
is_promotion = np.random.rand() < 0.2 # 20%的概率有促销
if is_promotion:
promotion_discount = np.random.uniform(0.7, 0.9) # 7-9折
current_price = round(current_price * promotion_discount, 2)
# 模拟销量 (价格越低,销量越高;有促销销量也高)
# 基础销量受价格影响
base_demand = 1000 / current_price + np.random.normal(0, 5)
if is_promotion:
base_demand *= np.random.uniform(1.2, 1.5) # 促销增加销量
sales_volume = max(0, int(base_demand + np.random.normal(0, 10))) # 增加随机波动
data.append([pid, current_date, base_price, current_price, is_promotion, sales_volume])
df_price_sensitivity = pd.DataFrame(data, columns=['product_id', 'date', 'base_price', 'current_price', 'is_promotion', 'sales_volume'])
return df_price_sensitivity
df_price_analysis = generate_price_sensitivity_data(num_products=50)
print("--- 价格敏感性数据预览 ---")
print(df_price_analysis.head())
# --- 不同价格区间的销售表现 ---
print("\n--- 不同价格区间的销售表现 ---")
# 1. 对价格进行分箱
price_bins = [0, 50, 100, 200, 300, 500, 1000]
price_labels = ['0-50', '51-100', '101-200', '201-300', '301-500', '501-1000']
df_price_analysis['price_range'] = pd.cut(df_price_analysis['current_price'], bins=price_bins, labels=price_labels, right=True)
# 2. 统计每个价格区间的平均销量
sales_by_price_range = df_price_analysis.groupby('price_range')['sales_volume'].mean().reset_index()
print("\n不同价格区间的平均销量:\n", sales_by_price_range)
# 可视化不同价格区间的平均销量
plt.figure(figsize=(10, 6))
sns.barplot(x='price_range', y='sales_volume', data=sales_by_price_range, palette='coolwarm')
plt.title('不同价格区间的商品平均销量')
plt.xlabel('价格区间 (元)')
plt.ylabel('平均销量')
plt.xticks(rotation=45, ha='right')
plt.show()
# --- 促销对销量的影响 ---
print("\n--- 促销对销量的影响 ---")
# 比较有促销和无促销时的平均销量
promotion_effect = df_price_analysis.groupby('is_promotion')['sales_volume'].mean().reset_index()
promotion_effect['is_promotion'] = promotion_effect['is_promotion'].map({True: '有促销', False: '无促销'})
print("\n促销对平均销量的影响:\n", promotion_effect)
# 可视化促销效果
plt.figure(figsize=(6, 5))
sns.barplot(x='is_promotion', y='sales_volume', data=promotion_effect, palette='pastel')
plt.title('促销对销量的影响')
plt.xlabel('是否促销')
plt.ylabel('平均销量')
plt.show()
# 更精细的分析:比较促销前后的销量变化
# 选取一个商品进行观察
product_to_analyze = np.random.choice(df_price_analysis['product_id'].unique())
df_single_product = df_price_analysis[df_price_analysis['product_id'] == product_to_analyze].sort_values(by='date')
plt.figure(figsize=(12, 6))
sns.lineplot(x='date', y='sales_volume', data=df_single_product, label='销量')
sns.lineplot(x='date', y='current_price', data=df_single_product, label='价格', color='red', linestyle='--')
# 标记促销日期
for index, row in df_single_product[df_single_product['is_promotion']].iterrows():
plt.axvline(x=row['date'], color='gray', linestyle=':', alpha=0.7)
plt.title(f'商品 {product_to_analyze} 价格与销量趋势 (虚线为促销日)')
plt.xlabel('日期')
plt.ylabel('销量 / 价格')
plt.legend()
plt.show()
# 【运营策略建议】
print("\n--- 基于价格敏感性分析的运营策略建议 ---")
print("1. **定价策略优化:** 根据价格区间和销量关系,找到最优价格点,或者针对不同价格敏感度的用户群体设定不同价格。")
print("2. **促销效果评估:** 持续监测促销活动对销量的实际影响,优化折扣力度和促销时机。")
print("3. **差异化定价:** 对于价格敏感度低的商品,可以考虑提价;对于价格敏感度高的商品,则需谨慎定价。")
【互动问答】
- 如何根据价格敏感性分析的结果,为新品定价提供建议?
- 除了我们分析的这些,还有哪些因素会影响商品的销量?(提示:品牌、评论、季节、竞品等)
- 在进行促销效果评估时,除了平均销量,还需要考虑哪些指标?(例如:毛利、用户转化率)
- 如何设计一个A/B测试来验证新的定价策略是否有效?
- 如果一个商品的价格变动很小,但销量变化很大,说明它的价格敏感度是高还是低?