某无人机航拍服务平台运营情况分析
数据背景
数据来源:某无人机航拍服务平台的订单数据
这份数据是我通过 scrapy 框架爬取该平台网站公开的订单数据得到的。数据仅以分析之用,故在下文中,特意隐藏该平台网站的信息。
分析目的:
- 分析该平台的运营情况
- 总结如果开展同类型项目可能会出现的问题
爬虫思路:
- 根据网站链接 http://www.abc.cn/page/job_xxx.html 中「xxx」,从 xxx=55 作递增处理;
- 爬取订单详情页里所有与订单有关的属性,并以 csv 的文件格式保存到本地。
最后共抓取到 138 条带有效数据的链接,在该网站中代表着有 138 个公开的订单。
数据概况
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
%matplotlib inline
pd.options.display.max_rows = 250
df = pd.read_csv('../scrapy_projects/abc/abc.csv')
df = df[['标题', '任务日期', '任务天数', '地点', '预算', '最终报价', '抢单飞手', '已选飞手', '服务评分', '电池块数', '拍摄内容', '人员配置', '拍摄机型', '飞手飞龄', '飞行环境', '拍摄用途', '任务说明']]
print(df.duplicated().value_counts()) # duplicated() 为 False 的有 138,代表 df 的每条数据都是非重复的。
df
结论
df 是一个 138x18 的不重复的数据集,也代表有着 138 个有效订单数据;
结合网站时间跨度从 2016 年 12 月 24 日,到最新更新的任务订单的日期 2017 年 10 月 23 日,相隔 303 天,跟订单数相除,平均 2.19 天一个订单。
任务日期分布(按月)
df['任务日期'] = df['任务日期'].str.split(" ", expand=True).get(0)
df['任务日期'] = df['任务日期'].str.replace("年|月", "-")
df['任务日期'] = df['任务日期'].apply(lambda x: x[0:7])
print("每月的订单分布如下:\n\n", df.groupby(by='任务日期').size())
每月的订单分布如下:
任务日期
2016-12 10
2017-01 14
2017-02 7
2017-03 16
2017-04 21
2017-05 22
2017-06 25
2017-07 14
2017-08 3
2017-09 4
2017-10 2
dtype: int64
from matplotlib.font_manager import FontProperties
font_zh = FontProperties(fname='/Library/Fonts/Microsoft/SimHei.ttf')
# for style in plt.style.available:
plt.style.use('fivethirtyeight')
ax = df.groupby(by='任务日期').size().plot(kind='line', ylim=(0,30), title="订单日期分布(按月)")
ax.title.set_fontproperties(font_zh)
ax.set_xlabel("月份").set_fontproperties(font_zh)
ax.set_ylabel("订单总数").set_fontproperties(font_zh)
结论
由上面的折线图,2 月份和 8 月份的订单数量有明显的回落,2 月份是农历新年假期,数据回落可以理解。但在 8 月份,订单数量骤降至只有 3 个订单,有几个可能性,一是用户需求量突然下降,二是关闭了用户自行发布需求的入口(改成现在这种由平台的运营进行选择性发布)。不过我不清楚他们之前发布需求的方式,所以现在还只是推测。如果第二种可能性是真的,那很可能他们在 8 月份的时候便开始内部调整了。
省份城市分布
df['省份'] = df['地点'].str.split(" ", expand=True).get(0)
df['城市'] = df['地点'].str.split(" ", expand=True).get(1)
# 对缺少「省」「市」的字段进行填补
df.loc[df['省份'].isin(['广东', '湖南', '山东', '黑龙江']), '省份'] += '省'
df.loc[df['省份'].isin(['北京', '上海']), '省份'] += '市'
plt.rcParams['font.sans-serif']=['SimHei']
plt.style.use('ggplot')
font_zh = FontProperties(fname='/Library/Fonts/Microsoft/SimHei.ttf')
ax = df['省份'].value_counts()[:10].plot(kind='pie', figsize=(6,6))
ax.title.set_fontproperties(font_zh)
# ax.set_fontproperties(font_zh)
ax.set_title('订单省份分布', fontsize=20)
df.loc[df['城市'].str.len()==2, '城市'] += '市'
df.loc[df['城市']=='哈尔滨', '城市'] += '市'
# 对「城市」列上空白字符的值,可以根据「地点」列的值进行提取
df.loc[df['城市']=='', '城市'] = df.loc[df['城市']=="", '地点'].str.split(" ", expand=True).get(3)
ax = df['城市'].value_counts()[:10].plot(kind='bar', title='订单城市分布')
ax.title.set_fontproperties(font_zh)
结论
结合「订单省份分布」及「订单城市分布」的图表,过半数的订单来自广东,同时订单量前十的城市中,有 4 个来自广东的,也符合「发迹于珠三角」的战略路线。
交易数据
df.loc[:, '预算'] = df['预算'].str.replace("¥", "").astype('float32')
df.loc[:, '最终报价'] = df['最终报价'].str.replace("¥", "").astype('float32')
df['差价'] = df['预算'] - df['最终报价']
print("订单成交金额:",df['最终报价'].sum())
订单成交金额: 404459.0
bins = [0, 1000, 2000, 3000, 4000, 5000, 10000, 20000]
level = ['1000以下', '1000-2000', '2000-3000', '3000-4000', '4000-5000', '5000-10000', '10000以上']
df['level'] = pd.cut(df['预算'], bins=bins, labels=level)
df_price_pct = pd.DataFrame(df['level'].value_counts())
df_price_pct['pct'] = ((df_price_pct['level']/df_price_pct['level'].sum())*100).round(2)
df_price_pct = df_price_pct.sort_index(axis=0, level=['1000以下', '1000-2000', '2000-3000', '3000-4000', '4000-5000', '5000-10000', '10000以上'])
df_price_pct
plt.style.use('bmh')
df_price_pct['level'].plot(kind='pie', title='订单预算价格', figsize=(6,6))
结论
- 订单的预算,即需求方的报价,介于 500 至 19500,平均预算为 3119.93 元,平均接单价(最后报价)2930.86 元,平均下来,比预算节省 189.07 元。
- 将最终报价进行汇总处理,可得知所有订单的成交金额为: 404459 元,假设网站抽佣高达 10%,网站将受益 40445.9 元。考虑到统计时间段横跨 10 个月,所以网站靠订单抽佣的方式盈利金额其实并不高。
- 由上面的饼图可得知,订单预算金额在 2000 元以下的已经超过一半了。再扩大范围,预算金额在 4000 以下的则高达 78.26%。可见客单价较低会是比较普遍的情况。
抢单数据
print("平均每个订单的抢单数:",df['抢单飞手'].mean().round(2))
平均每个订单的抢单数: 13.22
df['抢单飞手'].describe()
count 138.000000
mean 13.217391
std 11.230004
min 1.000000
25% 6.000000
50% 11.000000
75% 15.750000
max 75.000000
Name: 抢单飞手, dtype: float64
print("中标团队数量:", len(df['已选飞手'].unique()))
df_team = df['已选飞手'].value_counts().reset_index()
df_team[df_team['已选飞手']>1]
print("中标多于 1 单的团队数量:", len(df_team[df_team['已选飞手']>1]))
print("中标团队平均服务评分:", df['服务评分'].mean().round(2))
中标团队数量: 97
中标多于 1 单的团队数量: 19
中标团队平均服务评分: 87.64
结论
- 从「抢单飞手」一列的平均数据得知,平均每个订单的抢单数为 13.22,对需求方是个正反馈不错的数值。
- 这 138 个订单,实际上只有 97 个团队成果「中标」过,但「中标」数量多于 1 的团队只有 19 个,那就说明还有 78 个团队是只「中标」过一次。还没包括没有出现在这份数据上的,没有成功「中标」过的团队。所以该网站对服务方(飞手团队)的正反馈十分匮乏。
任务说明
df['任务说明'] = df['任务说明'].str.strip()
df['任务说明'] = df['任务说明'].str.replace("\r|\n|\t", "")
import re
# pat = r'【(\s+)([\u4e00-\u9fa5]+)(\s+)】| 【([\u4e00-\u9fa5]+)】'
pat = r'【(.*?)+】| [(.*?)+]'
df.loc[:, '标题'] = df['标题'].str.replace(pat , "")
text = "".join(df['标题'].values.tolist())
import jieba
segments = []
wordlist = jieba.cut(text, cut_all=True)
for seg in wordlist:
if len(seg)>1:
segments.append(seg)
segmentDF = pd.DataFrame({'segment': segments})
segstat = segmentDF.groupby('segment').size().reset_index()
segstat = segstat.rename(columns = {0:'counts'})
segstat = segstat.sort_values(by='counts', ascending=False)
segstat.head(10)
结论
单从订单的标题里分析拍摄需求,除「航拍」「拍摄」外,「建筑」这个词出现次数最高,证明建筑航拍在航拍需求量里是最高的,但鉴于数据量较小,此处的结论应辅以其他字段的分析进行验证。
小结
月订单数据在 8 月份开始突然骤降,一是可能跟团队内部调整有关,可以研究网站背后运作的公司的其他产品的动态辅以论证。二是可能这种商业模式依然不明朗,虽然平均订单单价 2930.86 元,但订单价在 2000 元以下的依然占超过一半,并且作为网站核心数据的订单量并不高,说明网站还处于低频低客单价的状态。从订单量看,需要结合他们团队的推广手段,来评估核心数据不高是因为推广力度不足,还是因为行业需求量偏低导致的。至于客单价的问题,可以考虑加入附加值更高的航拍服务(如电力航拍、测绘航拍)来提高订单价格。