数据预处理
注:代码中出现的文件路径改成自己的。
首先整合几个附件里的数据,先将附件一中‘单品名称’、‘单品编码’、‘分类名称’三者建立起关系,因为分类编码一共就6个,可以直接查找,就没有整理到json中。
import pandas as pd
import json
# 读取 Excel 文件
df = pd.read_excel('附件1.xlsx')
# 定义要包含在 JSON 对象中的列名
columns = ['单品名称', '单品编码', '分类名称']
# 为每一行创建 JSON 对象
json_objects = []
for index, row in df.iterrows():
json_object = {}
json_object['item_name'] = row[columns[0]]
json_object['item_code'] = row[columns[1]]
json_object['category_name'] = row[columns[2]]
json_objects.append(json_object)
# 将所有 JSON 对象组成一个 JSON 数组并写入文件
with open('your_json_name.json', 'w') as f:
json.dump(json_objects, f, indent=2) # indent=2 用于添加缩进,使 JSON 更易读
# 打印 JSON 对象
for obj in json_objects:
print(obj)
部分输出结果如下:
{'item_name': '牛首生菜', 'item_code': 102900005115168, 'category_name': '花叶类'}
{'item_name': '四川红香椿', 'item_code': 102900005115199, 'category_name': '花叶类'}
{'item_name': '本地小毛白菜', 'item_code': 102900005115625, 'category_name': '花叶类'}
…………
{'item_name': '海鲜菇(袋)(2)', 'item_code': 106930274620090, 'category_name': '食用菌'}
{'item_name': '绣球菌', 'item_code': 106931885000035, 'category_name': '食用菌'}
{'item_name': '绣球菌(袋)', 'item_code': 106931885000356, 'category_name': '食用菌'}
{'item_name': '金针菇(袋)(3)', 'item_code': 106949711300068, 'category_name': '食用菌'}
{'item_name': '金针菇(袋)(2)', 'item_code': 106949711300167, 'category_name': '食用菌'}
{'item_name': '金针菇(盒)', 'item_code': 106949711300259, 'category_name': '食用菌'}
{'item_name': '白玉菇(2)', 'item_code': 106956146480197, 'category_name': '食用菌'}
{'item_name': '蟹味菇(2)', 'item_code': 106956146480203, 'category_name': '食用菌'}
…………
然后找到‘单品编码’和‘销量(千克)’的Excel文件(附件二),计算每种单品的累加销量,以待后用:
import pandas as pd
# 读取 Excel 文件获取单品编码和销量
sales_data = pd.read_excel('附件2.xlsx')
sales_dict = sales_data.groupby('单品编码')['销量(千克)'].sum().to_dict()
# 累加相同单品编码的销量
accumulated_sales = {}
for item_code, sales in sales_dict.items():
if item_code in accumulated_sales:
accumulated_sales[item_code] += sales
else:
accumulated_sales[item_code] = sales
# 打印累加后的结果
for item_code, accumulated_sales_value in accumulated_sales.items():
print(f"单品编码: {item_code}, 累加销量: {accumulated_sales_value}")
输出结果如下:
……
单品编码: 102900011036266, 累加销量: 3.0
单品编码: 102900011036686, 累加销量: 27.0
单品编码: 102900051000463, 累加销量: 1047.689
单品编码: 102900051000890, 累加销量: 0.671
单品编码: 102900051000944, 累加销量: 745.554
……
这里可以将累加销量的内容保存到txt文件中,以待后用。
再转化为Excel来可视化
import pandas as pd
import json
# 从 output.json 文件读取数据
with open('your_json_name.json', 'r') as file:
data = json.load(file)
# 将数据转换为 DataFrame
df = pd.DataFrame(data)
# 将数据保存为 Excel 文件
df.to_excel('your_excel_name.xlsx', index=False)
import pandas as pd
# 读取 txt 文件
with open('your_txt_name.txt', 'r') as txt_file:
lines = txt_file.readlines()
# 处理每一行数据
data = []
for line in lines:
parts = line.split(',')
item_code = parts[0].split(': ')[1].strip()
cumulative_sales = float(parts[1].split(': ')[1].strip())
data.append([item_code, cumulative_sales])
# 将从 txt 文件中读取的数据转换为 DataFrame
df_txt = pd.DataFrame(data, columns=['item_code', 'cumulative_sales'])
# 读取 Excel 文件
df_excel = pd.read_excel('your_excel_name.xlsx')
# 将 Excel 和 txt 中的单品编码都转换为字符串类型
df_excel['item_code'] = df_excel['item_code'].astype(str)
df_txt['item_code'] = df_txt['item_code'].astype(str)
# 获取 Excel 中单品编码列的数据
excel_item_codes = df_excel['item_code'].values
# 找出 txt 中单品编码在 Excel 中对应的行索引
matching_indices = [i for i, code in enumerate(excel_item_codes) if code in df_txt['item_code'].values]
# 更新累计销量
for index in matching_indices:
matching_item_code = df_excel.loc[index, 'item_code']
matching_sales = df_txt[df_txt['item_code'] == matching_item_code]['cumulative_sales'].values[0]
df_excel.loc[index, 'cumulative_sales'] = matching_sales
# 保存更新后的 Excel 文件
df_excel.to_excel('your_excel_name.xlsx', index=False)
这样就形成了如下形式的excel文件(截取部分):
item_name | item_code | category_name | cumulative_sales |
牛首生菜 | 102900005115168 | 花叶类 | 899.837 |
四川红香椿 | 102900005115199 | 花叶类 | 333.223 |
本地小毛白菜 | 102900005115625 | 花叶类 | 121.02 |
白菜苔 | 102900005115748 | 花叶类 | 718.676 |
苋菜 | 102900005115762 | 花叶类 | 5100.061 |
云南生菜 | 102900005115779 | 花叶类 | 15910.46 |
品类丰富度
在此处可以先讨论各个分类的单品个数(即6种蔬菜的品类丰富度),来先进行一步分析:
import pandas as pd
# 读取 Excel 文件
df = pd.read_excel('your_excel_name.xlsx')
# 按 category_name 分组,计算每个组内的 item_name 数量
category_item_count = df.groupby('category_name')['item_name'].nunique()
print(category_item_count)
输出结果如下:
category_name
水生根茎类 19
花叶类 100
花菜类 5
茄类 10
辣椒类 45
食用菌 72
Name: item_name, dtype: int64
可以画出对应的饼状图:
import matplotlib.pyplot as plt
# 解决中文显示问题
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# 数据
categories = ['水生根茎类', '花叶类', '花菜类', '茄类', '辣椒类', '食用菌']
counts = [19, 100, 5, 10, 45, 72]
# 计算百分比
total = sum(counts)
percentages = [count / total * 100 for count in counts]
# 绘制饼状图
plt.pie(percentages, labels=categories, autopct='%1.1f%%')
plt.axis('equal')
plt.title('不同类别占比')
plt.show()
图片如下:
热销单品
从刚刚整理好的Excel文件中找到销量排名前10的单品:
import pandas as pd
# 读取 Excel 文件
df = pd.read_excel('your_excel_name.xlsx')
# 按照"cumulative_sales"列降序排序
sorted_df = df.sort_values(by='cumulative_sales', ascending=False)
# 选取排名前十的单品
top_ten_items = sorted_df.head(10)
# 打印结果
print(top_ten_items[['item_name', 'cumulative_sales']])
输出结果如下:
item_name cumulative_sales
148 芜湖青椒(1) 28164.331
100 西兰花 27537.228
106 净藕(1) 27149.440
16 大白菜 19187.218
5 云南生菜 15910.461
241 金针菇(盒) 15596.000
57 云南生菜(份) 14325.000
124 紫茄子(2) 13602.001
180 西峡香菇(1) 11920.227
157 小米椒(份) 10833.000
六大品类蔬菜季度平均销量
先从附件2中整理每季度各种单品的销售量:
import pandas as pd
def get_quarter(date):
month = date.month
if 1 <= month <= 3:
return 1
elif 4 <= month <= 6:
return 2
elif 7 <= month <= 9:
return 3
else:
return 4
# 读取 Excel 文件
df = pd.read_excel('附件2.xlsx')
# 将销售日期列转换为日期格式
df['销售日期'] = pd.to_datetime(df['销售日期'])
# 添加季度列
df['季度'] = df['销售日期'].apply(get_quarter)
# 按季度和单品编码分组,计算销量总和
quarterly_sales = df.groupby(['季度', '单品编码'])['销量(千克)'].sum().reset_index()
# 确保单品编码列是字符串类型
quarterly_sales['单品编码'] = quarterly_sales['单品编码'].astype(str)
# 将结果写入 Excel 文件
quarterly_sales.to_excel('quarterly_sales.xlsx', index=False)
获得的quarterly_sales.xlsx截取部分如下:
季度 | 单品编码 | 销量(千克) |
1 | 102900005115168 | 171.376 |
1 | 102900005115199 | 173.268 |
1 | 102900005115250 | 1402.589 |
1 | 102900005115748 | 684.023 |
1 | 102900005115762 | 562.951 |
1 | 102900005115779 | 2687.335 |
1 | 102900005115786 | 284.373 |
1 | 102900005115793 | 54.954 |
1 | 102900005115823 | 1933.838 |
利用第一步得到的json文件将单品编码对应的单品名称以及分类名称找出来,就可以得到更清晰的关系:
import pandas as pd
import json
# 读取 Excel 文件
quarterly_sales = pd.read_excel('quarterly_sales.xlsx')
# 读取 JSON 文件
try:
with open('your_json_name.json', 'r') as file:
code_name_data = json.load(file)
except FileNotFoundError:
print("The file was not found.")
code_name_data = []
# 将 JSON 数据转换为 DataFrame
code_name_df = pd.DataFrame(code_name_data)
# 重命名列以匹配现有 DataFrame 中的列名
code_name_df.rename(columns={'item_code': '单品编码', 'item_name': '单品名称', 'category_name': '分类名称'}, inplace=True)
# 使用 merge 将单品名称和分类名称添加到 quarterly_sales DataFrame
quarterly_sales = pd.merge(quarterly_sales, code_name_df, on='单品编码', how='left')
# 如果找不到对应的单品名称或分类名称,则填充特殊的单品编码
quarterly_sales['单品名称'] = quarterly_sales['单品名称'].fillna('SPECIAL_CODE')
quarterly_sales['分类名称'] = quarterly_sales['分类名称'].fillna('SPECIAL_CATEGORY')
# 确保单品编码列是字符串类型
quarterly_sales['单品编码'] = quarterly_sales['单品编码'].astype(str)
# 将更新后的 DataFrame 写入 Excel 文件
quarterly_sales.to_excel('quarterly_sales_updated.xlsx', index=False)
得到的quarterly_sales_updated.xlsx文件截取如下:
季度 | 单品编码 | 销量(千克) | 单品名称 | 分类名称 |
1 | 102900005115168 | 171.376 | 牛首生菜 | 花叶类 |
1 | 102900005115199 | 173.268 | 四川红香椿 | 花叶类 |
1 | 102900005115250 | 1402.589 | 西峡花菇(1) | 食用菌 |
1 | 102900005115748 | 684.023 | 白菜苔 | 花叶类 |
1 | 102900005115762 | 562.951 | 苋菜 | 花叶类 |
1 | 102900005115779 | 2687.335 | 云南生菜 | 花叶类 |
1 | 102900005115786 | 284.373 | 竹叶菜 | 花叶类 |
1 | 102900005115793 | 54.954 | 小白菜 | 花叶类 |
1 | 102900005115823 | 1933.838 | 上海青 | 花叶类 |
1 | 102900005115854 | 124.982 | 萝卜叶 | 花叶类 |
现在只需要对同一个分类的销量按照季度进行累加即可:
import pandas as pd
import matplotlib.pyplot as plt
# 读取 Excel 文件
df = pd.read_excel('quarterly_sales_updated.xlsx')
# 解决中文显示问题
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
# 按季度和分类名称分组,并计算每个分组的销量总和
category_sales_by_quarter = df.groupby(['季度', '分类名称'])['销量(千克)'].sum().reset_index()
# 重新排序列以适应季度和分类名称
category_sales_by_quarter = category_sales_by_quarter.pivot(index='季度', columns='分类名称', values='销量(千克)')
# 填充 NaN 值,将没有销量的分类名称设置为 0
category_sales_by_quarter.fillna(0, inplace=True)
# 打印表格
print(category_sales_by_quarter)
# 绘制曲线图
for column in category_sales_by_quarter.columns:
plt.plot(category_sales_by_quarter.index, category_sales_by_quarter[column], label=column)
plt.xlabel('季度')
plt.ylabel('销量(千克)')
plt.title('各分类季度销量曲线')
plt.legend()
plt.show()
结果如图: