我们如何在一个包含商品的表格中有效地确定订单是否只包含我们的产品/第三方产品还是混合的?

问题描述 投票:0回答:1

我有一个Python数据集,其中有OrderNumbers、IsOurs、产品是否是我们的以及产品的成本金额。我们希望对每个订单进行分类,无论它是否仅包含我们的产品,是否包含产品的混合或仅包含其他产品的产品。我们可以按如下方式生成数据集:

# Number of orders and products
num_orders = 1000
max_products_per_order = 10

# Generate random OrderNumbers
order_numbers = np.repeat(np.arange(1, num_orders + 1), np.random.randint(1, max_products_per_order + 1, num_orders))

# Generate IsOurs column with random True/False values
is_ours = np.random.choice([True, False], size=len(order_numbers))

# Generate unique ProductID
product_ids = np.arange(1, len(order_numbers) + 1)

# Generate random amounts for each product
np.random.seed(42)  # Set seed for reproducibility
amounts = np.round(np.random.uniform(10, 500, size=len(order_numbers)), 2)

# Create the DataFrame
df = pd.DataFrame({
    'OrderNumber': order_numbers,
    'ProductID': product_ids,
    'IsOurs': is_ours,
    'Amount': amounts
})

现在,为了计算它,我们可以执行以下操作:

第一个解决方案

df['OnlyOurs'] = df.groupby(['OrderNumber'])['IsOurs'].transform('all')
df['Mixed'] = df.groupby(['OrderNumber'])['IsOurs'].transform('any')
df['Mixed'] = df.Mixed & (df.OnlyOurs == False)
df['OnlyOther'] = (df.Mixed == False) & (df.OnlyOurs == False)
df['MixClass'] = "Mix"
df.loc[df['OnlyOther'], 'MixClass'] = "Other"
df.loc[df['OnlyOurs'], 'MixClass'] = "Ours"
df.groupby('MixClass')['Amount'].sum()

在我的电脑上,运行时间约为 40 毫秒,相当快。

如果我们写得优雅一点的话就是:

第二种解决方案

df['MixClass'] = df.groupby('OrderNumber')['IsOurs'].transform(
    lambda x: 'Ours' if x.all() else 'Other' if not x.any() else 'Mix')

这运行速度明显慢了。我想知道我是否遗漏了一些关于如何提高单衬管性能的信息。我知道这是因为在第一个解决方案中我使用矢量化函数,在第二个解决方案中我没有定义自己的函数。然而,我想知道是否存在更优雅的方法,而不需要那么多“样板”代码。

提前谢谢您。

python-3.x pandas dataframe
1个回答
0
投票

您可以使用

np.select

g = df.groupby('OrderNumber')['IsOurs']
condlist = [g.transform(f) for f in ['all', 'any']]
choicelist = ['Ours', 'Mix']
df['MixClass'] = np.select(condlist, choicelist, default='Other')

时间:

%timeit first_solution(df.copy())
%timeit second_solution(df.copy())
%timeit np_select(df.copy())

2.08 ms ± 590 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
84.7 ms ± 22.6 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
913 µs ± 31.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

平等

df_second.equals(df_np_select)
# True
© www.soinside.com 2019 - 2024. All rights reserved.