python 计算订单量最多的店铺订货金额

您所在的位置:网站首页 奶茶店怎么订货 python 计算订单量最多的店铺订货金额

python 计算订单量最多的店铺订货金额

2024-07-12 11:06:20| 来源: 网络整理| 查看: 265

作为数据分析师,除了熟练各种分析工具外,更重要的是分析、解决问题的能力以及扎实的数学功底,尤其是统计学。

本文将用一个例子,一步一步展示1)分析问题的步骤,2)更具需求选择合适工具和数据获取,3)和统计学知识在实例中的运用。

本文涉及例子和数据纯属虚构,如有雷同纯属巧合。

商业问题:是否需要多招一个奶茶工?

我的朋友小文在大学城开了一个奶茶店。由于开在大学城,奶茶店生意稳定,从周一到周日生意都差不多。现在奶茶店里有2个员工做奶茶,而点单则是由自助点单机器负责。一天小文去店里看运营情况,收到顾客反映等待时间太久,希望奶茶店再招些员工让等待时间短一些。考虑到工资成本,小文找到我让我帮助分析下是否需要再招个人,如果我可以出一个让他信服的商业分析报告,他就免费送我20杯奶茶的礼券。那我肯定不能错过这个免费喝奶茶的机会,于是和小文了解了奶茶店的情况后制定了以下分析步骤:分析、理解问题

获取、导入数据

数据清洗

数据分析与可视化

构建模型

总结

1. 分析、理解问题

与小文交流后,我把小文的问题“是否需要再招一个奶茶工?”转换成以下问题:为了提高顾客满意度,分析决定是否有95%的顾客实际等待时间超过他们的预期等待时间,如果是则小文需要至少再招一个人。

量化问题是解决问题的重要步骤之一。也就是说,需要量化等待时间来决定是否多招人,而不是因为有几个顾客反映等待时间过长的反馈进行决策。要解决等待时间是否过长需要2个数据指标:1)目标指标,95%顾客的可接受等待时间。2)客观计算或测量数据,95%的顾客的实际等待时间。

首先要确定目标指标。 这里95%顾客可接受等待时间是值顾客的心里预期,所以需要顾客主观给出一个认为可以接收的等待时间,而如果等待时间过长,久而久之等待时间过长的顾客就可以去其他奶茶店买奶茶了。因此,我决定使用15分钟或者以下。这里到了一些常用统计学知识,可以通过这篇文章了解为什么可以用样本去估计整体?以及这个回答,为什么设置95%?

下一步需要选择合适的方法得到顾客实际等待时间,我们可以通过以下方法:使用数学公式计算。对于如此多步骤的复杂问题,我们很难使用数据公式求解,因此使用数学公式不是合适选项。

实地测量顾客等待时间。实地测量是非常耗时耗力的,对于付出(一周甚至是更久的实地测量)回报(20杯奶茶)比来说,实地测量不是一个好的选择。

利用模拟实验得到等待时间。模拟实验是指使用代码来模拟当前卖奶茶的流程,并通过模拟实验模拟顾客的等待时间,如果模拟实验的数据能真实可靠地获得,那模拟实验就能很好地模拟真实情况。举个简单的例子理解模拟实验:一个袋子里有3个小球,一个红球,两个白球。问随便从袋子中取一个球,取到红球的概率。使用Python进行模拟实验可以使用以下代码。

import random

import numpy as np

# 模拟一个袋子,一个红球red,两个白球white

pocket = ['red', 'white', 'white']

# 记录每次摸球结果的列表

lst_result = []

# 模拟摸球1000000次

for t in range(1_000_000):

lst_result.append(random.choice(pocket))

# 计算1000000次摸球中,摸到红球的比例。

lst_result = np.array(lst_result)

print((lst_result== 'red').sum()/len(lst_result))0.333253

可以看到在一瞬间计算机就能进行一百万次模拟实验,最终得到摸到红球的概率是0.333253,所以在大量的模拟实验下,最终结果是非常接近真实结果的。其实对于这个简单的例子,概率公式1/3就能得到结果,但是对于卖奶茶的流程,不是简单的数学公式能计算出来的,而模拟实验正好能发挥他的作用。

接下来要衡量模拟实验的可行性。第一,整理卖奶茶的流程。下图为卖奶茶流程图:第二,检查数据是否可取得。

通过流程整理,我们知道模拟的第一步是模拟订单数据,那就需要历史订单数据。通过分析历史订单数据,我们可以得出规律并生模拟新的订单数据(主要是订单生成时间,和每单奶茶杯数)。

然后模拟第二步订单进入等待队列,产生的等待时间为t1,如果员工空闲那就可以立刻开始订单,此时t1=0。

模拟第三步员工制作奶茶,这时候需要每个员工制作奶茶的时间数据,并根据这一数据生成每杯奶茶的制作时间的模拟数据,而制作奶茶的时间为t2。最终就能得到每个订单的模拟等待时间t1+t2。

所以只要得到历史订单数据,和员工做每杯奶茶的时间就可以进行模拟。历史订单数据非常容易取得,只要从奶茶店销售系统中调取。员工做奶茶的时间并没有现成数据,于是我和小文商量了只要提供2个电子计时器,每次员工只要在开始和结束奶茶制作的时候按下计时器,就能得到奶茶制作时间。

经过以上思考,我们总结下问题。

解决的问题:为了提高顾客满意度,分析是否有95%的顾客实际等待时间超过他们的预期等待时间,来决定是否招人。

量化指标:1)95%顾客的预期等待时间。2)95%顾客的实际等待时间

方法选择:1)问卷调查获取顾客预期等待时间。2)模拟实验模拟实际等待时间。

数据需求:1)历史订单数据。2)收集员工做每杯奶茶的时间。

问题前提和假设:1)等待时间不包括点单时间,员工走动取单和送奶茶时间,只计算等待时间t1和奶茶制作时间t2作为总等待时间。2)期间没有任何促销,平均客流量稳定。3)顾客之间相互独立,即每位顾客来买奶茶不受其他顾客影响。4)员工做奶茶已经娴熟,做每杯奶茶的平均时间长期稳定,并且不同类型的奶茶平均制作时间一样。5)员工接到订单后完成整个订单,比如一个订单需要做3杯奶茶,则由一个员工完成所有奶茶。

2. 获取、导入数据

模拟实验用到了2个数据集-历史订单数据和员工做每杯奶茶的时间。这两个数据集是使用Python模拟的数据,非真实数据。

from collections import deque

from datetime import datetime

from scipy.stats import poisson, norm

from scipy.interpolate import make_interp_spline

import numpy as np

import random

import pandas as pd

from pylab import mpl

import matplotlib.pylab as plt # 数据可视化

plt.style.use('ggplot') # 设置风格使图标更美观

mpl.rcParams['font.sans-serif'] = ['SimHei'] # 指定字体雅黑,使图标可以显示中文

mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题

file_dir = r'/mnt/data-ubuntu/Projects/data_science_chinese'

df_lead_time = pd.read_csv(file_dir + r'/input/da_statics/lead_time.csv')

df_sales = pd.read_csv(file_dir + r'/input/da_statics/sales_sample.csv')

# 随便看一组数据

df_sales[df_sales['sample_group']== 934]

df_sales是在历史销售数据集中随机抽取了2000个小时的订单生成时间和下单杯数。sample_group是随机抽取小时的编号,time是在对应小时内订单生成时间,order_qty是在对应订单的奶茶下单杯数。

df_sales.info()

RangeIndex: 40269 entries, 0 to 40268

Data columns (total 3 columns):

# Column Non-Null Count Dtype

--- ------ -------------- -----

0 sample_group 40269 non-null int64

1 time 40269 non-null object

2 order_qty 40269 non-null int64

dtypes: int64(2), object(1)

memory usage: 943.9+ KB

数据一共40269行,并无缺失数据。

# 查看员工每杯奶茶制作时间数据

df_lead_time.head()

work1代表记录的员工1做每杯奶茶的时间,单位秒。work2代表记录的员工2做每杯奶茶的时间,单位秒。

df_lead_time.info()

RangeIndex: 996 entries, 0 to 995

Data columns (total 2 columns):

# Column Non-Null Count Dtype

--- ------ -------------- -----

0 work1 996 non-null int64

1 work2 996 non-null int64

dtypes: int64(2)

memory usage: 15.7 KB

该数据有996行数据,并无缺失值。

3. 数据清洗

这2个数据集为模拟数据,简单整洁且无缺失值,不需要进行数据清洗。

4. 数据分析与可视化

我们的目标是在模拟实验中生成模拟订单,包含了在某一时间点生成订单与下单数量。所以我们分析历史数据订单生成有什么规律,和下单数量有什么规律。

此外,对于每个员工做一杯奶茶的时间也要进行分析并找出规律,以便在模拟实验中生成合理的制作时间。

4.1 历史订单数据

4.1.1 下单时间分析

对于单行数据我们很难看出规律,既然数据是根据一小时统计的,那我们看看一小时有多少订单生成。

# 每小时订单数量

df_sales.groupby('sample_group').count()['time'].head()sample_group

0 15

1 16

2 27

3 22

4 15

Name: time, dtype: int64

可以看到每小时的订单数量各不相同。接下来我们汇总下不同“每小时订单数量”的个数,并通过可视化呈现出来。

# 除以总小时数得到每种可能性的概率

df_sales \

.groupby('sample_group') \

.count()['time'] \

.value_counts(normalize = True)\

.sort_index() \

.plot(kind = 'bar',

figsize = (6,4),

title = '每小时订单数概率分布图')

plt.show()

# 每小时订单数平均值

mu = df_sales.groupby('sample_group').count()['time'].mean().astype('int')

print(f'每小时订单数的平均值为{mu}。')每小时订单数的平均值为20。

图的x轴是每小时订单数的可能值,y轴是每个值对应的概率,这些不同值对应概率的总和是1。可以看到每小时订单数在20的概率最高,这也与每小时订单数的平均值20相对应。

这个分布称为泊松分布(Poisson Distribution)。泊松分布是一种离散型概率分布,用来表示在一段时间内一个事件发生数量的概率分布,并且要求事件的平均值在这段时间中不改变,每个发生点之间独立无联系。比如一个公司一小时接听到电话的数量,有可能是1通电话,10通电话,或者是20通电话。他是一个不确定的随机事件,如果每小时接听到电话的平均数量是10,那我们就可以用平均数量构建一个泊松分布。

test_samples = poisson.rvs(10, size = 2000, random_state = 44)

pd.Series(test_samples) \

.value_counts(normalize = True) \

.sort_index() \

.plot(kind = 'bar',

figsize = (8,6),

title = f'每小时平均电话数为10的泊松分布图')

plt.show()

但使用泊松分布公式并不能生成我们希望的模拟数据,我们需要的数据是像df_sales中的time一样的订单时间数据,这样在模拟的时候才能知道在哪个时间点会有新订单生成。因此我们需要使用指数分布函数(exponential distribution)生成泊松分布点的时间间隔。

比如,起始时间是t0=0,第一个泊松分布点出现的时间是t1,第二个点是t2,第三个点是t3...以此类推,而t1-t0=x1为一个时间间隔,t2-t1=x2为第二个时间间隔...这一系列x为随机变量,我们可以使用指数分布函数生成随机时间间隔,从而构建符合泊松分布的事件。假设一个公司每小时接到的平均电话为10通,那我们就能这样生成随机电话事件:

avg_calls = 10 # 每小时平均电话数

timespan = 3600 # 每个模拟时长3600秒

start = 0 # 起始时间0秒

lst_calls = [] # 记录电话打进时间

for s in range(timespan):

# 生成随机时间间隔,random.expovariate 是random包中的指数函数。

time_interval = int(random.expovariate(avg_calls/timespan))

start += time_interval

# 限定时间是一小时

if start < timespan:

lst_calls.append(start)

lst_calls = [str(s)+'s' for s in lst_calls]

print(f'模拟一小时,一共收到{len(lst_calls)}通电话。分别在以下时间收到:')

print(','.join(lst_calls))

模拟一小时,一共收到17通电话。分别在以下时间收到:

169s,287s,486s,932s,1224s,1251s,1349s,1409s,1567s,1789s,2240s,2429s,2544s,3020s,3236s,3392s,3474s

这样我们就能生成符合泊松分布的事件发生的时间点,希望了解更多关于泊松分布的知识可以阅读这篇文章,以及这篇。接下来要解决如何生成每个订单的奶茶杯数。

4.1.2 订单奶茶杯数

每个订单的奶茶杯数是一个整数,我们希望通过分析历史销量得出出如何合理地生成每个订单的杯数。先看下每个订单的平均杯数的可能性:

df_sales.order_qty.value_counts()1 28246

2 8112

3 1970

4 1565

5 264

6 112

Name: order_qty, dtype: int64

在这个数据集中,绝大多数人买1杯到6杯,肯定也有人买超过6杯,但是在我们取样了这么多订单也没有出现大于6杯的样本,说明1到6杯已经基本包括了所有可能性,我们可以忽略超过6杯的极小情况。既然这样我们可以构建一个简单的概率模型来随机生成订单杯数。

df_sales.order_qty.value_counts(normalize = True).round(3)1 0.701

2 0.201

3 0.049

4 0.039

5 0.007

6 0.003

Name: order_qty, dtype: float64

这样便得到了所有杯数可能性的概率,这些概率的总和是1,所以只要生成一个0到1之间的随机数,这个随机数落在哪个概率区间就生成相应杯数。

df_sales \

.order_qty \

.value_counts(normalize = True) \

.round(3) \

.reset_index().T \

.loc[['order_qty'], :] \

.plot(kind = 'barh',

stacked=True,

figsize = (12, 2),

legend=False)

plt.show()

如上图所示,如果随机数落在红色区域杯数就是1,落在蓝色区域就是2,落在紫色区域就是3,以此类推,就能生成合理的随机杯数。

4.2 员工做每杯奶茶的时间

另一个需要模拟生成的是员工做每杯奶茶的时间。不同员工做奶茶的时间和做每杯奶茶的实时间都是不同的,因此为了更真实地模拟实际情况,做每杯奶茶的时间因基于一定的规则随机生成合理值。接下来我们就来找一下这个规则。

print('='*10 + 'worker1' + '='*10)

print(df_lead_time.work1.describe())

print('='*10 + 'worker2' + '='*10)

print(df_lead_time.work2.describe())==========worker1==========

count 996.000000

mean 149.211847

std 10.020797

min 121.000000

25% 142.000000

50% 149.000000

75% 156.000000

max 179.000000

Name: work1, dtype: float64

==========worker2==========

count 996.000000

mean 238.692771

std 19.100054

min 185.000000

25% 226.000000

50% 239.000000

75% 252.000000

max 297.000000

Name: work2, dtype: float64

可以看到员工1平均做一杯奶茶的时间短与员工2,并且员工1做每杯奶茶的时间比员工2稳定(员工1的标准差10小于员工2的标准差19)。我们再用图表看下员工1做奶茶时间的分布情况。

fig, ax = plt.subplots(figsize = (8,6))

ax.hist(df_lead_time.work1, alpha=0.4, density = True)

x = df_lead_time.work1.sort_values()

y = norm.pdf(x,

df_lead_time.work1.mean(),

df_lead_time.work1.std())

ax.plot(x, y,

'b-', lw = 3, alpha = .5, label='norm pdf')

ax.legend()

plt.title('员工1每杯奶茶制作时间分布图')

plt.show()

形状和订单的泊松分布很相似,但是不同的横坐标的时间是中心极限定理符合正态分布,关于通俗地理解中心极限定理可以阅读这篇文章。此外有些同学可能会觉得这个是抽样调查应该按照t分布计算标准差,但由于这个例子中样本量大我们直接使用总体的标准差计算公式。

知道了样本数据的平均值和标准差后,我们就可以使用scipy中norm.rvs()生成模拟数据。

5. 构建模型

这里的模型构建指的是根据买奶茶的流程,和分析得到的数据模拟方法来构建整个模拟实验。

模型主要分为以下几步:新订单生成

加入等待队列

员工制作奶茶

制作完成,计算等待时间

多次模拟实验

再构建模拟实验前,我们先创建订单的类和员工的类。

# 订单类

class Order:

def __init__(self, order_time, order_qty):

"""创建实例对象生成订单时间和订单杯数。Params:order_time: int订单生成的时间。order_qty: int订单杯数。Return:None."""

self.qty = order_qty

self.order_time = order_time

def waiting_time(self, current_time):

"""根据当期时间计算订单等待时间。Params:current_time: int当前时间。Return:current_time - self.order_time: int等待时间。"""

return current_time - self.order_time

# 员工类

class Worker:

def __init__(self, avg_making_time, std_making_time):

"""创建员工实例对象。Params:avg_making_time: float每杯奶茶平均制作时间。std_making_time: float每杯奶茶制作时间标准差。Return:None."""

self.avg = avg_making_time

self.std = std_making_time

self.current_order = None

self.time_remaining = 0

def start_new(self, new_order):

"""开始制作新的订单。根据第五点前提和假设,员工接到订单后完成整个订单,比如一个订单需要做3杯奶茶,则由一个员工完成所有奶茶。Params:new_order: Order objectOrder对象。Return:self.time_remaining: intnew_order中所有奶茶制作时间的总和。"""

self.current_order = new_order

self.time_remaining = 0

for cup in range(self.current_order.qty):

self.time_remaining += Worker.make_time(self.avg, self.std)

return self.time_remaining

def making(self):

"""开始制作新的订单。Params:new_order: Order objectOrder对象。Return:self.time_remaining: intnew_order中所有奶茶制作时间的总和。"""

if self.current_order:

self.time_remaining -= 1

if self.time_remaining 0):

new_order = queue.pop()

# 返回订单在等待队列的等待时间。

waiting_t = new_order.waiting_time(s)

# 员工接单,返回整单制作时间。

# 这里模拟实验与实际情况不同,因为在模拟中员工一接订单就生成了制作时长。

making_t = w1.start_new(new_order)

# 总等待时间等于 = 等待时间 + 制作时间, 换算成分钟方便与顾客预期对比。

lst_waiting.append(round((waiting_t + making_t)/60 , 2))

# 员工2情况与员工1相同。

if (not w2.is_busy()) & (len(queue)>0):

new_order = queue.pop()

waiting_t = new_order.waiting_time(s)

making_t = w2.start_new(new_order)

lst_waiting.append(round((waiting_t + making_t)/60 , 2))

w1.making() #员工1制作奶茶

w2.making() #员工2制作奶茶

return lst_waiting

# 进行5000个小时模拟实验。

num_sim = 5000

# 保存所有订单等待时间。

lst_w = []

for i in range(num_sim):

lst_w += simulation()

我们来分析下实验结果,看看小文是否需要再雇人。

lst_w.sort()

plt.figure(figsize=(8,6))

plt.hist(lst_w,

alpha=.6,

density = True,

bins=[0, 5, 10, 15, 20, 25, 30])

# 落在95%的订单等待时间

waiting_95p = lst_w[round(len(lst_w)*0.95)]

plt.axvline(waiting_95p,

color='k',

linestyle='dashed',

linewidth=3,

alpha = .6,

label = '95%等待时间线')

plt.title('顾客等待时间分布图')

plt.legend()

plt.show()

print(f'进行{num_sim}次模拟实验后的平均等待时间为{round(np.mean(lst_w), 2)}分钟。')

print(f'百分之95的顾客等待时间少于{waiting_95p}分钟。')进行5000次模拟实验后的平均等待时间为6.35分钟。

百分之95的顾客等待时间少于15.3分钟。

从上图看到,实验的平均等待时间只有6.35分钟,百分之95的顾客等待时间少于15.3分钟,稍稍大于顾客预期15分钟,但已与95%顾客的预期接近。相信小文的选择肯定是不再多付一个人的工资成本去提高不到5%的顾客满意度了。

6. 总结

通过本文例子我们学到:数据分析解决实际问题的思考方法和步骤,根据需求和实际情况选择工具,和获取数据。

如何在数据分析中利用统计学知识:1)随机抽样获取样本。2)使用泊松分布和简单概率分布模拟订单信息。3)利用正态分布模拟每杯奶茶的制作时间。

使用Python构建模拟实验为决策提供指导。

感谢您的阅读,您的喜欢和点赞是我分享的动力。有兴趣的同学可以点击这里获取文章Jupyter Notebook。



【本文地址】

公司简介

联系我们

今日新闻


点击排行

实验室常用的仪器、试剂和
说到实验室常用到的东西,主要就分为仪器、试剂和耗
不用再找了,全球10大实验
01、赛默飞世尔科技(热电)Thermo Fisher Scientif
三代水柜的量产巅峰T-72坦
作者:寞寒最近,西边闹腾挺大,本来小寞以为忙完这
通风柜跟实验室通风系统有
说到通风柜跟实验室通风,不少人都纠结二者到底是不
集消毒杀菌、烘干收纳为一
厨房是家里细菌较多的地方,潮湿的环境、没有完全密
实验室设备之全钢实验台如
全钢实验台是实验室家具中较为重要的家具之一,很多

推荐新闻


图片新闻

实验室药品柜的特性有哪些
实验室药品柜是实验室家具的重要组成部分之一,主要
小学科学实验中有哪些教学
计算机 计算器 一般 打孔器 打气筒 仪器车 显微镜
实验室各种仪器原理动图讲
1.紫外分光光谱UV分析原理:吸收紫外光能量,引起分
高中化学常见仪器及实验装
1、可加热仪器:2、计量仪器:(1)仪器A的名称:量
微生物操作主要设备和器具
今天盘点一下微生物操作主要设备和器具,别嫌我啰嗦
浅谈通风柜使用基本常识
 众所周知,通风柜功能中最主要的就是排气功能。在

专题文章

    CopyRight 2018-2019 实验室设备网 版权所有 win10的实时保护怎么永久关闭