解决一个典型的商业案例研究任务

news2024/11/18 3:25:14

介绍

印尼的一家公司 Gojek 通过移动应用程序提供运输和物流、食品和购物、支付、日常需求、商业、新闻和娱乐等服务,对经济做出了超过70亿美元的贡献。

它拥有 90 万注册商户、超过 1.9 亿次应用下载以及超过 200 万名司机能够在120分钟内完成超过18万个订单。我们将使用商业分析解决一个案例研究。以下是它提供的 20 多项服务中的最后一项:https://www.gojek.io/blog/food-debarkation-tensoba

28a3964bf93991386b30daa632958e03.jpeg
  • 运输与物流

    • Go-ride - 你的摩托车出租车,即本地的 Ojek

    • Go-car - 舒适的出行方式

    • Go-send - 在几个小时内发送或交付包裹

    • Go-box - 搬家服务,通过称重计费

    • Go-bluebird - 专属于Bluebird的乘车服务

    • Go-transit - 你的通勤助手,有或没有Gojek

  • 美食与购物

    • Go-mall - 从在线市场购物

    • Go-mart - 从附近商店送货上门

    • Go-med - 从持牌药房购买药品、维生素等。

  • 付款

    • Go-pay – 无现金支付

    • Go-bills – 快速简单地支付账单

    • Paylater – 现在下单,之后付款。

    • Go-pulsa – 数据或通话时间,随时随地充值。

    • Go-sure – 为你看重的东西投保

    • Go-give – 为重要的事情捐款

    • Go-investasi – 明智投资,更好地储蓄。

  • 日常需求

    • GoFitness – 允许用户进行瑜伽、普拉提和泰拳等运动

  • 商业

    • Go-biz – 经营和发展业务的商家#SuperApp

  • 新闻与娱乐

    • Go-tix – 预订节目,免排队

    • Go-play – 电影和连续剧应用程序

    • Go-games – 游戏技巧趋势

    • Go-news – 热门新闻

通过这些服务生成的数据非常庞大,GO 团队拥有解决日常数据工程问题的工程解决方案。中央分析和科学团队(CAST)使 Gojek 生态系统中的多种产品能够有效地使用应用程序工作中涉及的大量数据。

该团队拥有分析师、数据科学家、数据工程师、业务分析师和决策科学家,致力于开发内部深度分析解决方案和其他 ML 系统。

5e63d5d73ec1ff426cabc74b9ee9c644.jpeg

分析师的角色集中于解决日常业务问题、拥有良好的业务知识、创造影响、获得见解、RCA(根本原因分析),并让高层管理人员了解微观和宏观指标以及产品决策来解决业务问题。

学习目标

  • 对组织面临的增长驱动因素和阻力进行根本原因分析

    • 使用 Pandas 进行 EDA、切片和切块

  • 营销预算优化

    • 利润作为北极星指标(L0指标)

    • 使用 Pulp 求解器求解 LP

    • 使用 Pulps 编写 LP 问题

  • 线性回归和交叉验证

    • 使用问卷中提供的步骤进行简单的回归练习。

目录

  • 介绍

  • 问题陈述

    • 第一部分

    • 第二部分

    • 第三部分

  • 数据集

  • 第一部分的解决方案

  • 对组织面临的增长驱动因素和阻力进行根本原因分析

  • 已完成的乘车订单

  • 取消的乘车订单

  • 订单分析

  • 业务分析的调查结果和建议摘要

  • 通过优化预算支出实现利润最大化

  • 了解优化数据集

  • 了解如何编写 LP 问题是解决它的关键

  • 第二部分的解决方案

  • 第三部分的解决方案

  • 有用的资源和参考

  • 结论

问题陈述

第一部分

GOJEK 董事已要求 BI 分析师查看数据,以了解 2016 年第一季度发生的情况,以及他们应该如何做才能最大限度地提高 2016 年第二季度的收入。

  • 鉴于问题 A 中的数据,我们需要关注的主要问题是什么?

  • 根据表 B 中的数据,如果我们只有 40,000,000,000 印尼盾(印度尼西亚的法定货币)的预算,你将如何最大化利润?

  • 在管理会议上展示你的发现和具体解决方案。

第二部分

  • 使用多元线性回归,预测 total_cbv。

  • 为每个服务创建 1 个模型。

  • 预测时期 = 2016-03-30、2016-03-31 和 2016-04-01

  • 训练周期 = 要使用的预测列表:

    • 一个月中的哪一天

    • 月份

    • 一周中的哪一天

    • 周末/工作日标志(周末 = 周六和周日)

  • 预处理(按顺序进行):

    • 删除 GO-TIX

    • 仅保留“已取消”订单状态

    • 确保存在日期和服务的完整组合(笛卡尔积)

    • 用 0 估算缺失值

    • 创建 is_weekend 标志预测器(如果周六/周日则为 1,如果其他日期为 0)

    • 对月份和星期几预测器进行one-hot编码

    • 仅使用训练周期数据的均值和标准差将所有预测变量标准化为 z 分数

  • 评估指标:MAPE 验证:3 折方案。每个验证折的长度与预测时期的长度相同。

  • 问题 1 – 在所有预处理步骤之后,service = GO-FOOD,date = 2016-02-28 的所有预测变量的值是多少?

  • 问题 2 – 显示one-hot编码变量的前 6 行(月份和星期几)

  • 问题 3 – 打印 service = GO-KILAT 预处理后的前 6 行数据。按日期升序排序

  • 问题 4 – 计算每项服务的预测期 MAPE。根据 MAPE 升序显示

  • 问题 5 – 创建图表以显示每个验证折的性能。一图一服务。X = date, y = total_cbv。Color:black = actual total_cbv,other colors = the fold predictions(应该有 3 种其他颜色)。只显示有效期。例如,如果第 11、12 和 13 行用于验证,则不要在图中显示其他行。在 x 轴上清楚地显示月份和日期

第三部分

我们在 Surabaya 的 GO-FOOD 服务上个月表现非常好——他们上个月完成的订单比前一个月多了 20%。Surabaya GO-FOOD 的经理需要了解正在发生的事情,以便在下个月继续保持这种成功。

  • 你会用什么定量方法来评估突然增长?你将如何评估客户的行为?

数据集

  • 第 1 部分

    • 表 A:https://github.com/chrisdmell/Project_DataScience/blob/working_branch/09_gojek/sales_data_all.csv

    • 表 B:https://github.com/chrisdmell/Project_DataScience/blob/working_branch/09_gojek/optimization_budge.csv

  • 第 2 部分

    • https://github.com/chrisdmell/Project_DataScience/blob/working_branch/09_gojek/model_analytics__data.csv

第一部分的解决方案

在开始解决之前,需要研究公司网站上的博客和白皮书(链接在下面添加)。公司档案提供了有用的资源,可以作为指南,帮助理解公司的立场。

问题一和问题三可视为开放式问题。第二个问题是关于回归的简单练习,不一定关注最佳模型,但重点是构建模型所涉及的过程。

对组织面临的增长驱动因素和阻力进行根本原因分析

导入数据:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import os
#import csv


sales_df =pd.read_csv('https://raw.githubusercontent.com/chrisdmell/Project_DataScience/working_branch/09_gojek/sales_data_all.csv')

print("Shape of the df")
display(sales_df.shape)

print("HEAD")
display(sales_df.head())

print("NULL CHECK")
display(sales_df.isnull().any().sum())

print("NULL CHECK")
display(sales_df.isnull().sum())

print("df INFO")
display(sales_df.info())

print("DESCRIBE")
display(sales_df.describe())
5e5c72c5ff2f1452d0d11533db2cf76c.jpeg

从对象格式创建 Pandas 日期时间。Pandas 日期时间是一种易于处理和操作日期的格式。

从日期时间派生月份列。也过滤掉第 4 个月(4 月)。将月份重命名为一月、二月、三月。

### convert to date time 
# convert order_status to strinf
##

time_to_pandas_time = ["date"]

for cols in time_to_pandas_time:
  sales_df[cols] = pd.to_datetime(sales_df[cols])

sales_df.dtypes

sales_df['Month'] = sales_df['date'].dt.month 
sales_df.head()

sales_df['Month'].drop_duplicates()

sales_df[sales_df['Month'] !=4]

Q1_2016_df = sales_df[sales_df['Month'] !=4]

Q1_2016_df['Month'] = np.where(Q1_2016_df['Month'] == 1,"Jan",np.where(Q1_2016_df['Month'] == 2,"Feb",np.where(Q1_2016_df['Month'] == 3,"Mar","Apr")))

print(Q1_2016_df.head(1))

display(Q1_2016_df.order_status.unique())

display(Q1_2016_df.service.unique())
#import csv
2226d4a25e7e83b56e6d9732db8588bf.jpeg 8d483c0c82ffbd61939158f002cb1eaa.jpeg

在集团层面,整体收入增长了 14%。这是一个积极的结果。

让我们按各种服务对此进行分解,并确定表现良好的服务。

revenue_total.sort_values(["Jan"], ascending=[False],inplace=True)

revenue_total.head()

revenue_total['cummul1'] = revenue_total["Jan"].cumsum()
revenue_total['cummul2'] = revenue_total["Feb"].cumsum()
revenue_total['cummul3'] = revenue_total["Mar"].cumsum()

top_95_revenue = revenue_total[revenue_total["cummul3"]<=95 ] 

display(top_95_revenue)
ninety_five_perc_gmv = list(top_95_revenue.service.unique())
print(ninety_five_perc_gmv)

top_95_revenue_plot = top_95_revenue[["Jan", "Feb", "Mar"]]
top_95_revenue_plot.index = top_95_revenue.service
top_95_revenue_plot.T.plot.line(figsize=(5,3))

### share of revenue is changed but has the overall revenue changed for these top 4 services#import csv
f994ba90b515fbe914efa943f884f9a9.jpeg de8ee9de0a4ba06e4802f855b0863847.jpeg
  • 在这三个月中,乘车、美食、购物和网购贡献了超过 90% 的净收入份额。(1 月,乘车贡献了 51% 的净收入。)

  • 因此,根据最近一个月的82原则,我们可以将此分析限制在前 3 项服务,即 - 乘车、食品、网购。

  • 在 11 项可用服务中,只有 3 项贡献了超过 90% 的收入。这是一个令人担忧的问题,其余服务的增长机会巨大。

已完成的乘车订单

### NET - completed rides
Q1_2016_df_pivot_cbv_4 = Q1_2016_df[Q1_2016_df["order_status"] == "Completed"]
Q1_2016_df_pivot_cbv_4 = Q1_2016_df_pivot_cbv_4[Q1_2016_df_pivot_cbv_4.service.isin(ninety_five_perc_gmv)]

Q1_2016_df_pivot_cbv = Q1_2016_df_pivot_cbv_4.pivot_table(index='service', columns=['Month' ], values='total_cbv', aggfunc= 'sum')
# display(Q1_2016_df_pivot_cbv.head())
Q1_2016_df_pivot_cbv = Q1_2016_df_pivot_cbv[["Jan", "Feb",  "Mar"]]

for cols in Q1_2016_df_pivot_cbv.columns:
  Q1_2016_df_pivot_cbv[cols]=(Q1_2016_df_pivot_cbv[cols]/1000000000)

display(Q1_2016_df_pivot_cbv)

display(Q1_2016_df_pivot_cbv.T.plot())

### We see that go shop as reduced its revenue but others the revenue is constant. 

Q1_2016_df_pivot_cbv_4 = Q1_2016_df_pivot_cbv
Q1_2016_df_pivot_cbv_4.reset_index(inplace = True)

Q1_2016_df_pivot_cbv_4["Feb_jan_growth"] = (Q1_2016_df_pivot_cbv_4.Feb / Q1_2016_df_pivot_cbv_4.Jan -1)*100
Q1_2016_df_pivot_cbv_4["Mar_Feb_growth"] = (Q1_2016_df_pivot_cbv_4.Mar / Q1_2016_df_pivot_cbv_4.Feb -1)*100

display(Q1_2016_df_pivot_cbv_4)#import csv
23437633e7c2275687f6260b4dc7f793.jpeg 346422a14cd56d4b509ebb82eb092c5b.jpeg a0b03b4900af66963b4cbbeb645976fe.jpeg
  • 作为收入的驱动——Ride 增长了 19%(1 月至 3 月),而 Send 增长了 25%。

  • 食品销售量下降了7%,考虑到全球餐饮外卖业务的增长,这是一个令人担忧的主要原因。

取消的乘车订单

Q1_2016_df_pivot_cbv = Q1_2016_df[Q1_2016_df["order_status"] != "Completed"]
Q1_2016_df_pivot_cbv = Q1_2016_df_pivot_cbv.pivot_table(index='service', columns=['Month' ], values='total_cbv', aggfunc= 'sum')
Q1_2016_df_pivot_cbv = Q1_2016_df_pivot_cbv[["Jan", "Feb",  "Mar"]]

revenue_total = pd.DataFrame()

for cols in Q1_2016_df_pivot_cbv.columns:
  revenue_total[cols]=(Q1_2016_df_pivot_cbv[cols]/Q1_2016_df_pivot_cbv[cols].sum())*100

revenue_total.reset_index(inplace = True)
display(revenue_total.head())

overall_cbv =     Q1_2016_df_pivot_cbv.sum()
print(overall_cbv)
overall_cbv.plot()
plt.show()


overall_cbv =     Q1_2016_df_pivot_cbv.sum()
overall_cbv_df = pd.DataFrame(data = overall_cbv).T
display(overall_cbv_df)

overall_cbv_df["Feb_jan_growth"] = (overall_cbv_df.Feb / overall_cbv_df.Jan -1)*100
overall_cbv_df["Mar_Feb_growth"] = (overall_cbv_df.Mar / overall_cbv_df.Feb -1)*100

display(overall_cbv_df)

revenue_total.sort_values(["Jan"], ascending=[False],inplace=True)

revenue_total.head()

revenue_total['cummul1'] = revenue_total["Jan"].cumsum()
revenue_total['cummul2'] = revenue_total["Feb"].cumsum()
revenue_total['cummul3'] = revenue_total["Mar"].cumsum()

top_95_revenue = revenue_total[revenue_total["cummul3"]<=95 ] 

display(top_95_revenue)
ninety_five_perc_gmv = list(top_95_revenue.service.unique())
print(ninety_five_perc_gmv)
2740dedb799cdf071dfd354cf757677c.jpeg a0f3f88029a0babf6b85a4d7663f9376.jpeg
  • 收入损失增长了 6%。

  • 董事们可以加大力度将这一比例降至 5% 以下。

订单分析

Q1_2016_df_can_com = Q1_2016_df[Q1_2016_df.order_status.isin(["Cancelled", "Completed"])]
Q1_2016_df_can_com = Q1_2016_df_can_com[Q1_2016_df_can_com.service.isin(ninety_five_perc_gmv)]


Q1_2016_df_pivot = Q1_2016_df_can_com.pivot_table(index='service', columns=['order_status','Month' ], values='num_orders', aggfunc= 'sum')
Q1_2016_df_pivot.fillna(0, inplace = True)

multi_tuples =[
                ('Cancelled', 'Jan'),
               ('Cancelled', 'Feb'),
            ('Cancelled', 'Mar'),
            ('Completed', 'Jan'),
            ('Completed', 'Feb'),
            ('Completed', 'Mar')]

multi_cols = pd.MultiIndex.from_tuples(multi_tuples, names=['Experiment', 'Lead Time'])

Q1_2016_df_pivot = pd.DataFrame(Q1_2016_df_pivot, columns=multi_cols)


display(Q1_2016_df_pivot.columns)
display(Q1_2016_df_pivot.head(3))

Q1_2016_df_pivot.columns = ['_'.join(col) for col in Q1_2016_df_pivot.columns.values]

display(Q1_2016_df_pivot)
#import csv

Q1_2016_df_pivot["jan_total"] = Q1_2016_df_pivot.Cancelled_Jan  + Q1_2016_df_pivot.Completed_Jan
Q1_2016_df_pivot["feb_total"] = Q1_2016_df_pivot.Cancelled_Feb  + Q1_2016_df_pivot.Completed_Feb
Q1_2016_df_pivot["mar_total"] = Q1_2016_df_pivot.Cancelled_Mar  + Q1_2016_df_pivot.Completed_Mar

Q1_2016_df_pivot[ "Cancelled_Jan_ratio" ]    =Q1_2016_df_pivot.Cancelled_Jan/Q1_2016_df_pivot.jan_total
Q1_2016_df_pivot[ "Cancelled_Feb_ratio" ]=Q1_2016_df_pivot.Cancelled_Feb/Q1_2016_df_pivot.feb_total
Q1_2016_df_pivot[ "Cancelled_Mar_ratio" ]=Q1_2016_df_pivot.Cancelled_Mar/Q1_2016_df_pivot.mar_total
Q1_2016_df_pivot[ "Completed_Jan_ratio" ]=Q1_2016_df_pivot.Completed_Jan/Q1_2016_df_pivot.jan_total
Q1_2016_df_pivot[ "Completed_Feb_ratio" ]=Q1_2016_df_pivot.Completed_Feb/Q1_2016_df_pivot.feb_total
Q1_2016_df_pivot[ "Completed_Mar_ratio" ]  =Q1_2016_df_pivot.Completed_Mar/Q1_2016_df_pivot.mar_total

Q1_2016_df_pivot_1 = Q1_2016_df_pivot[["Cancelled_Jan_ratio"
,"Cancelled_Feb_ratio"
,"Cancelled_Mar_ratio"
,"Completed_Jan_ratio"
,"Completed_Feb_ratio"
,"Completed_Mar_ratio"]]

Q1_2016_df_pivot_1
a15a1d156ffe814598028b44df430987.jpeg
  • 3月份,Food、Ride、Send的订单取消比例分别为17%、15%和13%。

  • Food 的订单完成率从 1 月份的 69% 提高到 3 月份的 83%。这是一项重大改进。

### column wise cancellation check if increased
perc_of_cols_orders = pd.DataFrame()

for cols in Q1_2016_df_pivot.columns:
  perc_of_cols_orders[cols]=(Q1_2016_df_pivot[cols]/Q1_2016_df_pivot[cols].sum())*100
  
perc_of_cols_orders

perc_of_cols_cbv.T.plot(kind='bar', stacked=True)
perc_of_cols_orders.T.plot(kind='bar', stacked=True)
75e171965855c4697bae1af76690695c.jpeg a95c57a0dbef549bacf458bddbd78d6d.jpeg
  • 3 月,在所有被取消的订单中,Ride占72%,其次是Food(17%)和send(6%)。

业务分析的调查结果和建议摘要

3a2f657b192d36409e73e880877d5c56.jpeg
  • RIDE:

    • 收入的最大贡献者。

    • 3 月份取消订单(GMV)增长了 42%

    • 通过产品干预和新产品功能减少取消比例。

  • FOOD:

    • 取消的订单有所增加,但由于成本优化,成功遏制了GMV损失。

    • 通过减少成本和取消量来增加净收入。

    • 获取更多的客户。

  • SEND:

    • 取消的 GMV 和订单是令人担忧的主要原因。

    • 良好的乘车完成体验可以提高留存率,并通过留存率推动收入增长。

通过优化预算支出实现利润最大化

业务团队为第二季度制定了 400 亿美元的预算,并为每项服务设定了增长目标。对于每项服务,增量 100 次乘车的成本和第二季度的最大增长目标如下所示。

对Go-Box来说,再增加100个预订,需要花费40M,Q2的最大增长目标是7%。

63ab7ba236f11d97e5d199e429d527a5.jpeg

从上述分析中导入预算数据并使用销售数据。

budget_df =pd.read_csv('https://raw.githubusercontent.com/chrisdmell/Project_DataScience/working_branch/09_gojek/optimization_budge.csv')

print("Shape of the df")
display(budget_df.shape)

print("HEAD")
display(budget_df.head())

print("NULL CHECK")
display(budget_df.isnull().any().sum())

print("NULL CHECK")
display(budget_df.isnull().sum())

print("df INFO")
display(budget_df.info())

print("DESCRIBE")
display(budget_df.describe())


### convert to date time 
# convert order_status to string
##

time_to_pandas_time = ["date"]

for cols in time_to_pandas_time:
  sales_df[cols] = pd.to_datetime(sales_df[cols])

sales_df.dtypes

sales_df['Month'] = sales_df['date'].dt.month 
sales_df.head()

sales_df['Month'].drop_duplicates()

sales_df_q1 = sales_df[sales_df['Month'] !=4]
### Assumptions
sales_df_q1 = sales_df_q1[sales_df_q1["order_status"] == "Completed"]

# Q1_2016_df_pivot = Q1_2016_df.pivot_table(index='service', columns=['order_status','Month' ], values='num_orders', aggfunc= 'sum')

sales_df_q1_pivot = sales_df_q1.pivot_table(index='service', columns=['order_status'], values='total_cbv', aggfunc= 'sum')
sales_df_q1_pivot_orders = sales_df_q1.pivot_table(index='service', columns=['order_status'], values='num_orders', aggfunc= 'sum')

sales_df_q1_pivot.reset_index(inplace = True)
sales_df_q1_pivot.columns = ["Service","Q1_revenue_completed"]
sales_df_q1_pivot

sales_df_q1_pivot_orders.reset_index(inplace = True)
sales_df_q1_pivot_orders.columns = ["Service","Q1_order_completed"]

optimization_Df = pd.merge(
    sales_df_q1_pivot,
    budget_df,
    how="left",
    on="Service",

)

optimization_Df = pd.merge(
    optimization_Df,
    sales_df_q1_pivot_orders,
    how="left",
    on="Service",

)

optimization_Df.columns = ["Service", "Q1_revenue_completed", "Cost_per_100_inc_booking", "max_q2_growth_rate","Q1_order_completed"]
optimization_Df.head(5)
#import csv
61438c572a46d285e6b79c50f8f9eca8.jpeg
  • 对于 Box,Q1 收入为 23B,增量 100 次乘车的成本为 40M,其最大预期增长率为 7%,总乘车次数为 63K,每笔订单 370K。

是否有可能在可用预算为 40B 的情况下实现所有服务的最大增长率?

### If all service max growth is to be achived what is the budget needed? and whats the deficiet?
optimization_Df["max_q2_growth_rate_upd"]   = optimization_Df['max_q2_growth_rate'].str.extract('(\d+)').astype(int)                 ### extract int from string
optimization_Df["max_growth_q2_cbv"]        = (optimization_Df.Q1_order_completed *(1+ optimization_Df.max_q2_growth_rate_upd/100))  ### Q2 max orders based on Q1 orders
optimization_Df["abs_inc_orders"]           = optimization_Df.max_growth_q2_cbv-optimization_Df.Q1_order_completed                   ### Total increase in orders 
optimization_Df["cost_of_max_inc_q2_order"] = optimization_Df.abs_inc_orders * optimization_Df.Cost_per_100_inc_booking /100         ### Total Cost to get maximum growth for each serivce

display(optimization_Df)

display(budget_df[budget_df["Service"] == "Budget:"].reset_index())
budget_max = budget_df[budget_df["Service"] == "Budget:"].reset_index()
budget_max = budget_max.iloc[:,2:3].values[0][0]
print("Budget difference by")
display(budget_max-optimization_Df.cost_of_max_inc_q2_order.sum() )

### Therefore max of the everything cannot be achieved#import csv

答案是第 247B(247,244,617,204) 号需要更多预算才能实现所有服务的增长目标。

有没有可能在40B的可用预算下,所有服务都至少达到最大增长率的10%?

### Then what is the budget needed and what will the extra budget at hand??
optimization_Df["min_10_max_growth_q2_cbv"]        = (optimization_Df.Q1_order_completed *(1+ optimization_Df.max_q2_growth_rate_upd/1000))  ### atleast 10% of max if achieved, this is orders 
optimization_Df["min_10_abs_inc_orders"]           = optimization_Df.min_10_max_growth_q2_cbv-optimization_Df.Q1_order_completed             ### what is the increase in orders needed to achieve 10% orders growth
optimization_Df["min_10_cost_of_max_inc_q2_order"] = optimization_Df.min_10_abs_inc_orders * optimization_Df.Cost_per_100_inc_booking /100   ### Cost associatedfor 10% increase in orders 

display(budget_max-optimization_Df.min_10_cost_of_max_inc_q2_order.sum() )  ### Total budget remaining

display((budget_max-optimization_Df.min_10_cost_of_max_inc_q2_order.sum())/budget_max)  ### Budget utilization percentage 


optimization_Df["perc_min_10_max_growth_q2_cbv"] =( ( optimization_Df.max_q2_growth_rate_upd/1000))  ### atleast 10% of max if achieved, 7 to percent divide by 100, 10% of this number. divide by 10, so 1000
optimization_Df["perc_max_growth_q2_cbv"]        =( ( optimization_Df.max_q2_growth_rate_upd/100))   ### Max growth to be achieved

optimization_Df["q1_aov"] = optimization_Df.Q1_revenue_completed/optimization_Df.Q1_order_completed  ### Q1 average order value
optimization_Df["order_profitability"] = 0.1  ### this is assumption that 10% will be profit

optimization_Df["a_orders_Q2"]        = (optimization_Df.Q1_order_completed *(1+ optimization_Df.perc_min_10_max_growth_q2_cbv))  ### based on 10% growth, total new orders for qc

optimization_Df["a_abs_inc_orders"]   = optimization_Df.a_orders_Q2-optimization_Df.Q1_order_completed

optimization_Df["a_Q2_costs"] = optimization_Df.Cost_per_100_inc_booking* optimization_Df.a_abs_inc_orders/100

##There is scope for improvement here, so This can be adjusted based on revenue or ranking from Q1
display(budget_max - optimization_Df.a_Q2_costs.sum())

optimization_Df#import csv

答案是肯定的。只需可用 40B 预算的 28%,即可实现这一目标。可用预算的未充分利用绝不是一种选择,任何企业领导者都不会只使用可用预算的 28%。

因此,无法实现所有服务的最大增长,实现最大增长率的 10% 将导致预算无法得到充分利用。因此,这里需要优化支出,以便:

  • 整体现金消耗补不超过 40B。

  • 第二季度各服务的整体增长率等于或低于最大增长率。

  • 线性优化中称为约束。

  • 目标是利润最大化。

这里使用的假设:

  • 每项服务都有 10% 的利润。

  • AOV(收入/订单)将与第一季度保持一致。

预优化数据管道:

### Data prep for pulp optimization
perc_all_df = pd.DataFrame(data = list(range(1,optimization_Df.max_q2_growth_rate_upd.max()+1)), columns = ["growth_perc"])  
### create a list of all percentage growth, from 1 to max to growth expected, this is to create simulation for optimization
display(perc_all_df.head(1))

optimization_Df_2 = optimization_Df.merge(perc_all_df, how = "cross")  ### cross join with opti DF

### Filter and keeping all percentgaes upto maximum for each service
### Minimum percentage kept is 1
optimization_Df_2["filter_flag"] = np.where(optimization_Df_2.max_q2_growth_rate_upd >= (optimization_Df_2.growth_perc),1,0)
optimization_Df_2["abs_profit"] =  (optimization_Df_2.q1_aov)*(optimization_Df_2.order_profitability)
optimization_Df_3 = optimization_Df_2[optimization_Df_2["filter_flag"] == 1]


display(optimization_Df_3.head(1))
display(optimization_Df_3.columns)

### Filter columns needed
optimization_Df_4 = optimization_Df_3[[
    'Service',                       ### services offered
    'Cost_per_100_inc_booking',      ### cost of additional 100 orders
    'Q1_order_completed',            ### to calculate q2 growth based on q1 orders
    'perc_min_10_max_growth_q2_cbv', ### minimum growth percent need 
    'perc_max_growth_q2_cbv',        ### max growth percent allowed
    'abs_profit',                    ### profit per order 
    'growth_perc'                    ### to simulative growth percet across
    ]]

display(optimization_Df_4.head(2))


optimization_Df_4["orders_Q2"]        = (optimization_Df_4.Q1_order_completed *(1+ optimization_Df_4.growth_perc/100))  ### based on growth, total new orders for qc
optimization_Df_4["abs_inc_orders"]   = optimization_Df_4.orders_Q2-optimization_Df_4.Q1_order_completed
optimization_Df_4["profit_Q2_cbv"]    = optimization_Df_4.orders_Q2 * optimization_Df_4.abs_profit
optimization_Df_4["growth_perc"]      = optimization_Df_4.growth_perc/100
optimization_Df_4["Q2_costs"]         = optimization_Df_4.Cost_per_100_inc_booking* optimization_Df_4.abs_inc_orders/100

display(optimization_Df_4.head())

optimization_Df_5 = optimization_Df_4[[
    'Service',                       ### services offered
    'Q2_costs',                      ### cost total for the growth expected
    'perc_min_10_max_growth_q2_cbv', ### minimum growth percent need 
    'perc_max_growth_q2_cbv',        ### max growth percent allowed
    'profit_Q2_cbv',                 ### total profit at the  assumed order_profitability rate
    'growth_perc'                    ### to simulative growth percet across
    ]]

optimization_Df_5


display(optimization_Df_5.head(10))
display(optimization_Df_5.shape)
3c1f0430401d87e79cb0836fe2b54cc2.jpeg

了解优化数据集

  • Service – Go product

  • 最大增长的 10%,是每个服务应该达到的最小增长。所以 Box 至少应该实现 0.7% 的增长。

    • 这是一个约束。

  • 业务领导者为 Box 决定的最大增长是 7%。

    • 这是一个约束。

  • 对于Box,1%到7%是增长的范围。1%超过0.7%,7%是最大值。优化器将根据约束选择最佳增长率。

    • 这是一个决策变量。该算法将从 7 个中选择一个。

  • 对于 1% 的增长(增量),现金消耗为 2.55 亿。

    • 这是一个约束。

  • 如果增量增长率为 1%,则总体利润(有机 + 无机)为 2.4B。

    • 这是目标。

### Best optimization for our case case. This is good. 

prob = LpProblem("growth_maximize", LpMaximize)    ### Initialize optimization problem - Maximization problem

optimization_Df_5.reset_index(inplace = True, drop = True)   
markdowns = list(optimization_Df_5['growth_perc'].unique())   ### List of all growth percentages
cost_v    = list(optimization_Df_5['Q2_costs'])               ### List of all incremental cost to achieve the growth % needed

perc_min_10_max_growth_q2_cbv = list(optimization_Df_5['perc_min_10_max_growth_q2_cbv'])
growth_perc                   = list(optimization_Df_5['growth_perc'])

### lp variables
low     = LpVariable.dicts("l_", perc_min_10_max_growth_q2_cbv, lowBound = 0, cat = "Continuous")
growth  = LpVariable.dicts("g_", growth_perc, lowBound = 0, cat = "Continuous")
delta   = LpVariable.dicts ("d", markdowns, 0, 1, LpBinary)
x       = LpVariable.dicts ("x", range(0, len(optimization_Df_5)), 0, 1, LpBinary)

### objective function - Maximise profit, column name - profit_Q2_cbv
### Assign value for each of the rows -
### For all rows in the table each row will be assidned x_0, x_1, x_2 etc etc
### This is later used to filter the optimal growth percent 
prob += lpSum(x[i] * optimization_Df_5.loc[i, 'profit_Q2_cbv'] for i in range(0, len(optimization_Df_5)))

### one unique growth percentahe for each service
### Constraint one 
for i in optimization_Df_5['Service'].unique():
                prob += lpSum([x[idx] for idx in optimization_Df_5[(optimization_Df_5['Service'] == i) ].index]) == 1

### Do not cross total budget
### Constraint two
prob += (lpSum(x[i] * optimization_Df_5.loc[i, 'Q2_costs'] for i in range(0, len(optimization_Df_5))) - budget_max) <= 0 

### constraint to say minimum should be achived
for i in range(0, len(optimization_Df_5)):
  prob +=  lpSum(x[i] * optimization_Df_5.loc[i, 'growth_perc'] ) >=  lpSum(x[i] * optimization_Df_5.loc[i, 'perc_min_10_max_growth_q2_cbv'] )


prob.writeLP('markdown_problem')     ### Write Problem name
prob.solve()                         ### Solve Problem
display(LpStatus[prob.status])       ### Problem status - Optimal, if problem solved successfully
display(value(prob.objective))       ### Objective, in this case what is the maximized profit with availble budget  - 98731060158.842 @ 10% profit per order #import csv
print(prob)
print(growth)

了解如何编写 LP 问题是解决它的关键

  • 初始化问题

    • prob = LpProblem(“growth_maximize”, LpMaximize)

    • 问题的名称是 growth_maximize

    • LpMaximize 让求解器知道这是一个最大化问题。

  • 创建决策函数的变量

    • growth = LpVariable.dicts(“g_”, growth_perc, lowBound = 0, cat = “连续”)

    • 对于 Pulp,需要创建 pulp dicts

    • g_ 是变量的前缀

    • growth_perc 是列表的名称

    • low bound是最小增长百分比,可以从0开始。

    • 变量是连续的。

    • 有 60 个独特的增长百分比,从 1%(最小值)到 60%(最大值)。(食物的最大增长率为 60%)。

    • 变量 – 0 <= x_0 <= 1行0 到 0 <= x_279 <= 1行 279 的整数。

  • 为问题添加目标函数

    • prob += lpSum(x[i] * optimization_Df_5.loc[i, 'profit_Q2_cbv'] for i in range(0, len(optimization_Df_5)))

    • 创建了一个等式:  pulp -> 2423147615.954*x_0 + 2447139176.5080004*x_1 + 225916468.96*x_3+ … + 8576395.965000002*x_279。数据集中有 280 行,因此为每个利润值创建一个变量。

  • 添加约束:

    • display(LpStatus[prob.status])

    • for i in range(0, len(optimization_Df_5)): prob += lpSum(x[i] * optimization_Df_5.loc[i, 'growth_perc'] ) >= lpSum(x[i] * optimization_Df_5.loc[i, ' perc_min_10_max_growth_q2_cbv'] )

    • 对于每一行,创建最小增长百分比约束方程。有 279 行,因此创建了 279 个约束。

    • _C13:0.003 x_0 >= 0 从第 0 行到 _C292:0.315 x_279 >= 0 到第 279 行。

    • prob += (lpSum(x[i] * optimization_Df_5.loc[i, 'Q2_costs'] for i inrange(0, len(optimization_Df_5))) – budget_max) <= 0

    • 所有成本减去总预算的总和应小于或等于零。

    • 方程式 _C12:255040000 x_0 + 510080000 x_1 + …. + 16604 x_279 <= 0

    • _C12:是这里唯一的约束,因为有一个总预算为 40B,并且没有限制每个服务可以花费多少。

    • 对于 optimization_Df_5['Service'].unique() 中的 i: prob += lpSum([x[idx] for idx in optimization_Df_5[(optimization_Df_5['Service'] == i) ].index]) == 1

    • 对于每项服务,只选择一个增长百分比。

    • 从 1 到 7 个 Box 中只选择 1。

    • 方框的方程 – _C1:x_0 + x_1 + x_2 + x_3 + x_4 + x_5 + x_6 = 1

    • GLAM – _C2 的等式:x_10 + x_11 + x_12 + x_13 + x_14 + x_15 + x_16 + x_7 + x_8 + x_9 = 1

    • 由于有 11 个服务,因此创建了 11 个约束,每个服务一个约束。

    • 每项服务的一个增长百分比

    • 不要超过 40B 的总预算

    • 约束最低应该达到

    • “ Optimal” 是期望的输出

    • 98731060158.842  利润最大化

  • display(value(prob.objective))

var_name = []
var_values = []
for variable in prob.variables():
    if 'x' in variable.name:
        var_name.append(variable.name)
        var_values.append(variable.varValue)

results = pd.DataFrame()

results['variable_name'] = var_name
results['variable_values'] = var_values
results['variable_name_1'] = results['variable_name'].apply(lambda x: x.split('_')[0])
results['variable_name_2'] = results['variable_name'].apply(lambda x: x.split('_')[1])
results['variable_name_2'] = results['variable_name_2'].astype(int)
results.sort_values(by='variable_name_2', inplace=True)
results.drop(columns=['variable_name_1', 'variable_name_2'], inplace=True)
results.reset_index(inplace=True)
results.drop(columns='index', axis=1, inplace=True)

# results.head()


optimization_Df_5['variable_name'] = results['variable_name'].copy()
optimization_Df_5['variable_values'] = results['variable_values'].copy()
optimization_Df_5['variable_values'] = optimization_Df_5['variable_values'].astype(int)# optimization_Df_6.head()

#import csv### with no budget contraint
optimization_Df_10 = optimization_Df_5[optimization_Df_5['variable_values'] == 1].reset_index()

optimization_Df_10["flag"] = np.where(optimization_Df_10.growth_perc >= optimization_Df_10.perc_min_10_max_growth_q2_cbv,1,0)

display(optimization_Df_10)

display(budget_max - optimization_Df_10.Q2_costs.sum())
display( optimization_Df_10.Q2_costs.sum())
25dd91006027208039e10805beb8c8f0.jpeg
  • 各服务的最大增长率见上表。对于 Box,它是 1%,对于 Clean,它是 1%,对于 Food,它是 17%,等等。

  • 现金消耗总额为 – 39999532404.0

  • 未充分利用的预算 – 467596.0

  • 利润最大化 – 98731060158.0

第二部分的解决方案

sales_df =pd.read_csv('https://raw.githubusercontent.com/chrisdmell/Project_DataScience/working_branch/09_gojek/model_analytics__data.csv')

time_to_pandas_time = ["date"]

for cols in time_to_pandas_time:
  sales_df[cols] = pd.to_datetime(sales_df[cols])


sales_df['Month'] = sales_df['date'].dt.month 

Q1_2016_df = sales_df[sales_df['Month'] !=900]

Q1_2016_df['Month'] = np.where(Q1_2016_df['Month'] == 1,"Jan",np.where(Q1_2016_df['Month'] == 2,"Feb",np.where(Q1_2016_df['Month'] == 3,"Mar","Apr")))

Q1_2016_df['test_control'] = np.where(Q1_2016_df['date'] <= "2016-03-30","train", "test")

display(Q1_2016_df.head(5))

display(Q1_2016_df.order_status.unique())

display(Q1_2016_df.service.unique())

display(Q1_2016_df.date.max())
#import csv
  • 导入数据集

  • 将日期转换为 pandas 日期时间

  • 导出月份列

  • 导出训练和测试列

display(Q1_2016_df.head())
display(Q1_2016_df.date.max())

Q1_2016_df_2 = Q1_2016_df[Q1_2016_df["date"] <= "2016-04-01"]
display(Q1_2016_df_2.date.max())

Q1_2016_df_2 = Q1_2016_df_2[Q1_2016_df["order_status"]  == "Cancelled"] 

Q1_2016_df_date_unique = Q1_2016_df_2[["date"]].drop_duplicates()
Q1_2016_df_date_service = Q1_2016_df_2[["service"]].drop_duplicates()

Q1_2016_df_CJ = Q1_2016_df_date_unique.merge(Q1_2016_df_date_service, how = "cross")  ### cross join with opti DF

display(Q1_2016_df_date_unique.head())
display(Q1_2016_df_date_unique.shape)
display(Q1_2016_df_date_unique.max())
display(Q1_2016_df_date_unique.min())

display(Q1_2016_df_2.shape)
Q1_2016_df_3 = Q1_2016_df_CJ.merge(Q1_2016_df_2, on=['date','service'], how='left', suffixes=('_x', '_y'))

display(Q1_2016_df_3.head())
display(Q1_2016_df_3.shape)
display(Q1_2016_df_CJ.shape)

Q1_2016_df_3["total_cbv"].fillna(0, inplace = True)
print("Null check ",Q1_2016_df_3.isnull().values.any())

nan_rows = Q1_2016_df_3[Q1_2016_df_3['total_cbv'].isnull()]
nan_rows

display(Q1_2016_df_3[Q1_2016_df_3.isnull().any(axis=1)])

Q1_2016_df_3["dayofweek"] = Q1_2016_df_3["date"].dt.dayofweek
Q1_2016_df_3["dayofmonth"] = Q1_2016_df_3["date"].dt.day

Q1_2016_df_3["Is_Weekend"] = Q1_2016_df_3["date"].dt.day_name().isin(['Saturday', 'Sunday'])

Q1_2016_df_3.head()
  • 仅过滤已取消的订单

  • 对于所有服务,交叉连接从 1 月 1 日到 4 月 1 日的日期,以便所有日期的预测都可用

  • 将 NULL 替换为 0

  • 导出月份中的某天

  • 导出一周中的某天

  • 创建二进制周末/工作日列

d70a3ebb4480a43480390689d7c41aac.jpeg
Q1_2016_df_4 = Q1_2016_df_3[Q1_2016_df_3["service"] != "GO-TIX"]

Q1_2016_df_5 = pd.get_dummies(Q1_2016_df_4, columns=["Month","dayofweek"])

display(Q1_2016_df_5.head())


import numpy as np
import pandas as pd
# from sklearn.datasets import load_boston
from sklearn.preprocessing import Normalizer
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import KFold
from sklearn.model_selection import cross_val_score
from numpy import mean
from numpy import std
from sklearn.metrics import make_scorer
from sklearn.model_selection import cross_val_predict


Q1_2016_df_5.columns


all_columns = ['date', 'service', 'num_orders', 'order_status', 'total_cbv',
                'test_control', 'dayofmonth', 'Is_Weekend', 'Month_Apr', 'Month_Feb',
                'Month_Jan', 'Month_Mar', 'dayofweek_0', 'dayofweek_1', 'dayofweek_2',
                'dayofweek_3', 'dayofweek_4', 'dayofweek_5', 'dayofweek_6']

                
model_variables = [ 'dayofmonth', 'Is_Weekend', 'Month_Apr', 'Month_Feb',
                  'Month_Jan', 'Month_Mar', 'dayofweek_0', 'dayofweek_1', 'dayofweek_2',
                  'dayofweek_3', 'dayofweek_4', 'dayofweek_5', 'dayofweek_6']

target_Variable = ["total_cbv"]

all_columns = ['service', 
                'test_control', 'dayofmonth', 'Is_Weekend', 'Month_Apr', 'Month_Feb',
                'Month_Jan', 'Month_Mar', 'dayofweek_0', 'dayofweek_1', 'dayofweek_2',
                'dayofweek_3', 'dayofweek_4', 'dayofweek_5', 'dayofweek_6']
  • 过滤掉 GO-TIX

  • one-hot 编码——月份和星期几

  • 导入所有必要的库

  • 创建columns、train_predict 等列表。

model_1 = Q1_2016_df_5[Q1_2016_df_5["service"] =="GO-FOOD"]

test  = model_1[model_1["test_control"]!="train"]
train = model_1[model_1["test_control"]=="train"]

X = train[model_variables]
y = train[target_Variable]

train_predict = model_1[model_1["test_control"]=="train"]
x_ = X[model_variables]

sc = StandardScaler()
X_train = sc.fit_transform(X)
X_test = sc.transform(x_)
  • 为一项服务过滤数据 – GO-FOOD

  • 创建训练和测试数据框

  • 创建 X – 使用训练列,使用预测列创建 y。

  • 使用 Standardscalar 进行 z 分数转换。

#define custom function which returns single output as metric score
def NMAPE(y_true, y_pred): 
    return 1 - np.mean(np.abs((y_true - y_pred) / y_true)) * 100

#make scorer from custome function
nmape_scorer = make_scorer(NMAPE)

# prepare the cross-validation procedure
cv = KFold(n_splits=3, random_state=1, shuffle=True)
# create model
model = LinearRegression()
# evaluate model
scores = cross_val_score(model, X, y, scoring=nmape_scorer, cv=cv, n_jobs=-1)
# report performance
print('Accuracy: %.3f (%.3f)' % (mean(scores), std(scores)))

y_pred = cross_val_predict(model, X, y,  cv=cv)
  • cross_val_score 没有 MAPE 作为内置记分器,因此定义 MAPE。

  • 创建 CV 实例

  • 创建 LR 实例

  • 使用 cross_val_score 获取 GO-Foods 跨 CV 折的平均 MAPE 分数。

  • 对于每一个服务,这段代码都可以循环使用,创建一个函数:

def go_model(Q1_2016_df_5, go_service,model_variables,target_Variable):
  """
  Q1_2016_df_5
  go_service
  model_variables
  target_Variable
  """
  model_1 = Q1_2016_df_5[Q1_2016_df_5["service"] ==go_service]

  test  = model_1[model_1["test_control"]!="train"]
  train = model_1[model_1["test_control"]=="train"]

  X = train[model_variables]
  y = train[target_Variable]

  train_predict = model_1[model_1["test_control"]=="train"]
  x_ = X[model_variables]

  X_train = sc.fit_transform(X)
  X_test = sc.transform(x_)

  # prepare the cross-validation procedure
  cv = KFold(n_splits=3, random_state=1, shuffle=True)
  # create model
  model = LinearRegression()
  # evaluate model
  scores = cross_val_score(model, X, y, scoring=nmape_scorer, cv=cv, n_jobs=-1)
  # report performance
  print('Accuracy: %.3f (%.3f)' % (mean(scores), std(scores)))

  y_pred = cross_val_predict(model, X, y,  cv=cv)

  return y_pred,mean(scores), std(scores)

a,b,c = go_model(Q1_2016_df_5, "GO-FOOD",model_variables,target_Variable)

b
  • 转换为函数的建模步骤:

    • Q1_2016_df_5 – 基础数据

    • go_service – go-tix、go-send 等

    • model_variables – 用于训练模型的变量

    • target_Variable – 预测变量(total_cbv)。

  • 对于每项服务,可以运行该方法以获得所有 11 项服务的平均预测 MAPE。

第三部分的解决方案

问题 3 是一个开放式问题,鼓励读者自行解决。一些假设是:

  • 由于这是特定于一个粒子区域和地理位置的,因此可以安全地假设 APP 或多或少保持不变,并且产品干预可能只起到了次要作用。如果有产品干预,它只是特定于这个特定领域。

  • 优质/著名的餐厅和食品连锁店已经上线,用户现在可以从熟悉的餐厅或熟悉的餐厅订购很多不错的选择。

  • 通过加入更多的送货代理,送货速度得到了显着提高。

  • 重新培训送货代理以减少取消的订单数目。

  • 与餐厅合作,以更好的方式处理高峰时段的混乱情况。

有用的资源和参考

  • 在“中央分析和科学团队”工作:https://www.gojek.io/blog/working-in-the-central-analytics-and-science-team

  • 如何使用“Tensoba”估算食物的送达时间:https://www.gojek.io/blog/food-debarkation-tensoba

  • 入门级数据分析师的商业案例研究任务:https://www.analyticsvidhya.com/blog/2023/02/business-case-study-assignments-for-entry-level-data-analysts/

  • 解决数据科学家的商业案例研究任务:https://www.analyticsvidhya.com/blog/2022/05/solving-business-case-study-assignments-for-data-scientists/

  • 使用数据来分析客户:https://www.gojek.io/blog/using-data-to-appreciate-our-customers

  • Gojek 自动预测工具的工作原理:https://www.gojek.io/blog/under-the-hood-of-gojeks-automated-forecasting-tool

  • Gojek 的实验:https://www.gojek.io/blog/beast-moving-data-from-kafka-to-bigquery

  • GO-JEK 对印度尼西亚的影响:https://www.gojek.io/blog/go-jeks-impact-for-indonesia

  • GO-FAST:Ramadan 背后的数据

    • https://www.gojek.io/blog/go-fast-the-data-behind-ramadan

  • PuLP 优化:https://medium.com/ro-co/optimization-with-pulp-in-python-getting-started-f6c5b678bf15

  • 使用 PuLP 的线性规划:https://towardsdatascience.com/basic-linear-programming-in-python-with-pulp-d398d144802b

  • 营销活动优化:https://www.kaggle.com/code/mozturkmen/replication-of-marketing-campaign-optimization

  • 使用 python 优化某些东西的简单方法:https://towardsdatascience.com/a-simple-way-to-optimize-something-in-python-740cda7fd3e0

结论

如果按照上述步骤正确完成案例研究,将对业务产生积极影响。招聘人员不是在寻找答案,而是在寻找获得这些答案的方法、遵循的结构、使用的推理以及使用业务分析的业务和实践知识。

本文以真实的业务案例研究为例,为数据分析师提供了一个易于遵循的框架。

☆ END ☆

如果看到这里,说明你喜欢这篇文章,请转发、点赞。微信搜索「uncle_pn」,欢迎添加小编微信「 woshicver」,每日朋友圈更新一篇高质量博文。

扫描二维码添加小编↓

7514b36072f0b6168435a5bf47645ac4.jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/604540.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

chatgpt赋能python:Python创建界面的重要性及实现方法

Python创建界面的重要性及实现方法 作为一名有10年Python编程经验的工程师&#xff0c;我深知Python在Web开发、数据分析和人工智能等方面的强大表现。然而&#xff0c;Python对于前端的支持一直是一个不被关注的领域。 随着网站、移动应用和电脑软件的普及&#xff0c;用户对…

Find My产品|Targus推出最新支持苹果Find My双肩包

Targus宣布推出 Cypress Hero Backpack 双肩包&#xff0c;最大的亮点在于支持苹果“Find My”&#xff0c;在丢失后可定位追踪。 Targus这款双肩包采用了环保材料&#xff0c;可以妥善地保护笔记本电脑&#xff0c;并提供丰富的收纳袋存放各种配件和物品。这款双肩包内置带衬…

Unity Addressables学习笔记(3)---加载远程场景Scenes

前言 Unity Addressables学习笔记—汇总 正文 1.创建一个新场景 我是创建在Resources/Scenes目录下&#xff0c;如图&#xff1a; 2.为场景创建一个Addressables的Group Game1Group就是我新创建的一个Group用来存放场景1的所有资源&#xff0c;分组的配置跟Remote一样&a…

vue 读取本地文件

1. vue读取本地文件 2.在文件夹下添加一个类 3.读取本地文件&#xff0c;先读取文件的内容 4.在 body下添加一个属性 5.读取后&#xff0c;写到 setTimeout方法中&#xff0c;返回一个错误信息。 6. restart方法&#xff0c;在组件渲染时调用 7. return setTimeout &#xff08…

使用Redis的zset集合实现小程序的滚动分页

一、 Redis中&#xff0c;使用有序集合&#xff08;sorted set&#xff09;实现滚动分页的原理如下&#xff1a; 将每个文档的 score 值设置为时间戳&#xff08;或根据其他规则计算的分数&#xff09;&#xff0c;将文档的 ID 作为 value&#xff0c;然后将其添加到有序集合中…

delphi 开发虚拟摄像头

用directshow创建一个虚拟摄像头 然后注册到系统&#xff0c; 在用一个main app 调用摄像头&#xff0c;往里面写流&#xff0c; 可以是屏幕录制&#xff0c;可以是播放的多媒体文件 然后具体是要实现录屏&#xff0c;或者播放多媒体文件&#xff0c;在虚拟摄像头插件中fil…

Godot 4 源码分析 - 初探

准备研究GoDot 4源码。 源码下载 获取源代码 在进入 SCons 构建系统并编译 Godot 之前&#xff0c;你需要将 Godot 的源代码下载到本地。 源代码位于 GitHub 上, 虽然你可以通过网站手动下载它, 但是通常你希望通过 git 版本控制系统来下载. 如果你是为了做贡献或拉动请求…

国产新秀---XS5018A,芯昇,图像信号处理芯片

国产视频处理芯片&#xff0c;大崛起。 XS5018A 是一款针对 CMOS 图像传感器的高性价比图像信号处理芯片&#xff0c;支持 1M/2M 像素 图像传感器&#xff0c;一组 10-bit DVP 输入接口&#xff0c; ISP 具备优异的 3D 降噪功能&#xff0c;标清模拟输出支持 960…

Java官方笔记6继承

继承 Java只有单继承&#xff0c;最顶级的父类是Object。 子类会继承父类的fields和methods&#xff0c;而不会继承constructors&#xff0c;因为constructors不属于methods&#xff0c;但是子类可以通过super调用父类的constructor。 子类继承父类的范围是&#xff1a;public、…

记录--让URL地址都变成了ooooooooo

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 发现一个很有创意的小工具网站&#xff0c;如封面图所示功能很简单&#xff0c;就是将一个URL地址转换为都是 ooooooooo 的样子&#xff0c;通过转换后的地址访问可以转换回到原始地址&#xff0c;简单…

chatgpt赋能python:Python创建Word文档指南

Python创建Word文档指南 在今天的数字时代&#xff0c;Word文档仍然是最常见和使用的文档类型之一。Python是一个强大的编程语言&#xff0c;可以用于自动化创建各种类型的文档&#xff0c;包括Word文档。在本篇文章中&#xff0c;我们将介绍如何使用Python创建Word文档&#…

Rust每日一练(Leetday0019) 跳跃游戏、合并区间、插入区间

目录 55. 跳跃游戏 Jump Game &#x1f31f;&#x1f31f; 56. 合并区间 Mmerge Intervals &#x1f31f;&#x1f31f; 57. 插入区间 Insert Interval &#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Rust每日一练 专栏 Golang每日一练 专…

KP3114电源IC介绍--【其利天下】

KP3114 是一款高性能低成本 PWM 控制功率开关&#xff0c;适用于离线式小功率降压型应用场合&#xff0c;外围电路简单、器件个数少。同时产品内置高耐压 MOSFET 可提高系统浪涌耐受能力。 与传统的 PWM 控制器不同&#xff0c;KP3114 内部无固定时钟驱动 MOSFET&#xff0c;系…

为什么陶瓷板视觉技术会越来越受到人们的青睐?

随着科技的不断进步和应用&#xff0c;陶瓷板视觉技术越来越受到人们的青睐。陶瓷板视觉技术是一种新型的非接触式检测技术&#xff0c;它可以在生产过程中对产品进行高效、准确的检测和质量控制。下面我们来详细了解一下陶瓷板视觉技术的优势和应用。 一、优势 1.高效性 陶…

10款抓包工具优缺点对比

1. Wireshark 介绍&#xff1a;Wireshark是一个免费的网络协议分析工具&#xff0c;支持Windows、macOS和Linux等多个平台。它可以捕获和分析网络数据包&#xff0c;支持多种网络协议解码。优点&#xff1a;功能强大、支持多种协议解码、支持多平台、过滤器功能强大、免费开源。…

QT+OpenGL实例化和抗锯齿

QTOpenGL实例化和抗锯齿 本篇完整工程见gitee:QtOpenGL 对应点的tag&#xff0c;由turbolove提供技术支持&#xff0c;您可以关注博主或者私信博主 实例化 如果我们需要渲染大量物体时&#xff0c; 代码看起来会像这样&#xff1a; for(int i 0; i < amount; i) {DoSom…

Mybatis 别名的配置 + Mybatis配置类的调查

参考资料 Mybatis配置类别名mybatis-spring-boot-autoconfigure类型别名&#xff08;typeAliases&#xff09;SpringBoot五步配置Mybatis超简教程 目录 一. 使用场景二. 前期准备2.1 实体类2.2 查询接口 三. 配置方式1 配置文件的方式3.1 application.yml文件3.2 SQL的XMl文件…

做完这些lab,国内外大厂横着走

hi&#xff0c;大家好&#xff0c;这里是极客重生&#xff0c;坚实的计算机基础&#xff0c;对我们发展都是至关重要的&#xff0c;不管是校招还是社招&#xff0c;因此我和小伙伴一起收集了一些国内外硬核lib和开源项目来帮助大家学习和巩固基础&#xff08;动手实践&#xff…

计算机组成原理 第一章_概述

typora-copy-images-to: images 文章目录 typora-copy-images-to: images1.现代计算机的结构2.各硬件的工作原理2.1 主存储器的基本组成2.2 运算器的基本组成2.3 控制器的基本组成2.4 计算机的工作过程 3.计算机系统的层次结构4. 计算机的性能指标4.1存储器的性能指标4.2 CPU的…

14-Vue3快速上手

目录 1.Vue3简介2. Vue3带来了什么2.1 性能的提升2.2 源码的升级2.3 拥抱TypeScript2.4 新的特性 1、海贼王&#xff0c;我当定了&#xff01;——路飞 2、人&#xff0c;最重要的是“心”啊&#xff01;——山治 3、如果放弃&#xff0c;我将终身遗憾。——路飞 4、人的梦想是…