Python中求解商品单价及处理订单异常值问题求助
解决
np.linalg.lstsq维度不匹配的问题 我来帮你搞定这个问题,你遇到的LinAlgError: Incompatible dimensions本质是因为你构建的矩阵完全不符合最小二乘法的要求——你把商品名称(字符串)和数量混在了一个数组里,而且单个订单的矩阵形状也不对。咱们一步步来修正:
问题根源分析
np.linalg.lstsq要求的输入是:
- 第一个参数X:是一个
(n_samples, n_features)的数值型矩阵,每一行代表一个样本(这里就是一个订单),每一列代表一个特征(这里是对应商品的订购数量) - 第二个参数y:是一个
(n_samples,)的数值型向量,对应每个样本的目标值(这里是订单总价)
你之前的操作把商品名称和数量拼成了(4,2)的字符串数组,这既不是数值矩阵,形状也不满足lstsq的要求,自然会报错。
正确的解决方案
我们需要把所有订单数据转换成符合要求的数值矩阵和目标向量,步骤如下:
1. 提取所有唯一商品名称
首先从所有订单里找出所有的商品,确定我们要求解的单价变量:
import numpy as np from collections import defaultdict # 你的示例数据 order_data = { 1215.5: [('Shrimp', 10), ('Fish&Chips', 6), ('Salmon', 8), ('Pasta', 5)], 1230.0: [('Shrimp', 10), ('Salmon', 10), ('Fish&Chips', 8)], 1234.0: [('Salmon', 9), ('Fish&Chips', 3), ('Pasta', 8), ('Shrimp', 10)], 1292.5: [('Pasta', 7), ('Salmon', 9), ('Fish&Chips', 7), ('Shrimp', 9)], 1301.5: [('Pasta', 5), ('Shrimp', 9), ('Salmon', 8), ('Fish&Chips', 10)], 1314.5: [('Shrimp', 10), ('Pasta', 5), ('Fish&Chips', 10), ('Salmon', 7)], 1343.5: [('Shrimp', 8), ('Fish&Chips', 10), ('Salmon', 9), ('Pasta', 7)] } # 获取所有唯一商品 all_products = list({product for order in order_data.values() for product, _ in order}) n_products = len(all_products) n_orders = len(order_data)
2. 构建系数矩阵X和目标向量y
对每个订单,按照all_products的顺序,生成对应商品的数量数组(没有订购的商品数量为0),同时收集订单总价:
# 初始化矩阵和向量 X = np.zeros((n_orders, n_products), dtype=np.float64) y = np.zeros(n_orders, dtype=np.float64) for i, (total_price, items) in enumerate(order_data.items()): y[i] = total_price # 把当前订单的商品数量映射到X的对应列 product_count = defaultdict(int) for product, count in items: product_count[product] = count # 填充X的第i行 for j, product in enumerate(all_products): X[i, j] = product_count[product]
现在X的形状是(7,4)(7个订单,4种商品),y的形状是(7,),完全符合lstsq的要求。
3. 调用最小二乘法求解单价
现在就可以正常调用np.linalg.lstsq了:
# 求解,rcond=None是为了适配新版本numpy的默认设置 prices, residuals, rank, singular_values = np.linalg.lstsq(X, y, rcond=None) # 把结果和商品对应起来 product_prices = dict(zip(all_products, prices)) print("各商品单价:") for product, price in product_prices.items(): print(f"{product}: {price:.2f}")
补充:如果只用单个订单怎么办?
如果你只想用单个订单(比如总价1234.0的那条)求解,那其实不需要最小二乘法,直接解线性方程组就行:
# 取目标订单 single_order_total = 1234.0 single_order_items = order_data[single_order_total] # 构建单个订单的系数矩阵(形状(1,4))和目标值 single_X = np.zeros((1, n_products)) single_y = np.array([single_order_total]) for j, product in enumerate(all_products): for p, cnt in single_order_items: if p == product: single_X[0, j] = cnt break # 解线性方程组 single_prices = np.linalg.solve(single_X, single_y) print("单个订单求解的单价:", dict(zip(all_products, single_prices)))
不过更推荐用多个订单做最小二乘,这样可以抵消部分异常订单的影响,得到更准确的单价,也方便后续识别异常值(比如残差过大的订单)。
内容的提问来源于stack exchange,提问作者leena
相关产品推荐
相关产品推荐

