精华内容
下载资源
问答
  • 移动互联网的兴起离不开各类APP的崛起,殊不知APP推广运营成本其实远高于开发成本,单就推广这一项,品途网接到了这样一篇接地气的投稿;通过它可以了解目前主流的APP推广方式(社会化SNS、第三方应用分发渠道)和...

      移动互联网的兴起离不开各类APP的崛起,殊不知APP推广运营成本其实远高于开发成本,单就推广这一项,品途网接到了这样一篇接地气的投稿;通过它可以了解目前主流的APP推广方式(社会化SNS、第三方应用分发渠道)和基本规则,供读者一览。

      桔子科技分别在6个渠道进行了测试性推广——微博、豆瓣、微信、安卓应用市场、APP STORE和新闻媒体网站,几乎没有花钱推广。大概情况如下:

      一、微博推广

      我个人微博和朋友的几个微博加起来真实粉丝有30万,这2个月经常给这个APP打广告,转发超1万的微博有过3条,转发超100的微博有过60条,微博带来的下载量转化率在10%左右,一条转发1万次的微博,带来的APP下载量1000左右,和我心里逾期的落差太大。后来我就问了很多粉丝,因为粉丝大部分都是学生,部分回答是没有WIFI,部分回答是没有强烈的需求,后来我就都集中在晚上9点以后发微博,效果比较好,下载量可以立竿见影,但是转化率也就20%左右。

      二、豆瓣推广

      我在豆瓣写过几个没节操的小说,最高的一条软文回帖超过了1万,还有几条软文回复也超过了3000次,转化率比较差,比平时下载量多个500左右。然后又找这些回帖的人做了个调研,很多人回复说软文太长,看了APP名字没有绝对这个是重点,就没有去下载,顶多记住了名字而已,看来我这植入软文写的太差了。后来我就直接在软文里面贴APP的截图,下载量又提高了那么一点,但也就一点点而已。

      三、微信推广

      我没有开通微信公众号,因为我自己都没有关注几个微信公众号,感觉这个东西推广不靠谱,但是我有1个微信私人号,好友数8000个,后来因微信政策变化,我就不能再加好友了。我主要还是在朋友圈推广,发一条广告APP的下载量在一个小时内可以增加500次左右,于是我就坚持每天发,发了2个月,差不多这8000个人都下载了APP了。看来还是要坚持对一个用户推销三次以上,用户才会接受。

      四、安卓应用市场

      1、首发

      看到应用宝说一次某应用在他家首发有60万下载量,我就屁颠屁颠的去申请了个应用宝首发,首发那天我一整天都守在友盟前面度过的,看了一天友盟,安卓下载量比平时一天多了……300……我真的没有说谎,就是多300,一个都不多。不吹牛会死啊,太失望了,带着对腾讯的失望,又申请了小米应用商店的首发,这个稍微靠谱点,首发给了4天广告位,4天总共安卓下载量有8000,后来我又申请了360首发、联想乐商店首发,效果和应用宝没有什么差别,惨不忍睹,再也不相信首发了。做了应用市场首发清单,供大家参考:

      应用商店申请入口首发申请要求首发天数

      360首发后台自助申请首发需要提交APK1或2天

      应用宝后台自助申请比较容易通过审核1天

      百度、91、安卓邮件申请日均下载量不得低于5001天

      小米应用商店邮件申请首发需要提交APK3或4天

      联想乐商店邮件申请比较容易通过审核2天

      2、礼包抽奖活动,这个是要花钱买奖品的,我好不容易说服公司拿了1.5万出来卖奖品,和3个应用商店做了抽奖活动,但是结果和不花钱的首发效果差不多,我估计公司以后再也不给我钱做推广了。以下是一个应用商店礼包抽奖名单,供大家阅读参考。

      商店名字申请入口奖品礼包金额

      豌豆荚邮件申请金额要求大于10,000

      小米应用商店邮件申请金额要求大于5,000

      360首发后台自助申请只接受应用内的虚拟奖品

      联想乐商店邮件申请金额要求大于3,000

      UC应用商店邮件申请金额要求大于3,000

      百度、91、安卓加工作人员QQ完全看他们个人喜好

      应用宝暂时只接受手游申请

      3、刷量,打开各安卓应用市场,排名靠前的应用,下载量都是几千万、几百万,基本都是刷量,除了小米和UC应用商店,国内所有的应用市场都可以刷量,目前刷量的价格基本是1万个量40元,至少要刷100万的量才能在分类里面有点排名。当然安卓也有刷榜,400元/天,7天起刷,不进总榜,进热门榜或飙升榜就算,刷量和刷榜都需要付费,我自己掏了500把百度应用的里面下载量刷到了20万……呵呵……估计也能骗到不少外行人。

      4、加后缀,起初我应用名字就是2个字,连个后缀都没有,后来我在名字后面加了个后缀词,当然这个词肯定是热门关键词,加了后缀之后,果然第二天开始下载量迅速提高了50%。从此到现在,我都在研究后缀,不过360、百度、豌豆荚、应用宝这四个应用市场都不让加后缀,只能在其他应用市场添加。

      五、APP STORE 推广

      1、找分类

      最早我把APP放在社交类,使劲在微博和豆瓣推了几天,好不容易稳定在分类160名左右,结果后来苹果的分类只显示前150,我再搞了几天月也没有办法稳定在150名,就干脆改到旅游类,结果马上稳定在前150了,目前稳稳在旅游类前120名。估计每天也能带来一点点下载量,如果能挤到前50名,应该会能带来很大的下载量。

      2、起名

      我研究了下社交排行榜前100名,很多排名靠前的APP,他们都有一个共同点:就是APP名字后面都接了一大串的低俗词语,如:寂寞、单身、约会、陌生人、婚恋、恋爱、性感、激情、相亲、妹子,美女等刺激男性荷尔蒙的词,于是我也在APP名字后面加上了捡妹子,结果排名立刻涨了20名,你别说,还真是有效。

      3、苹果刷榜

      因为公司预算紧张,我没有付费刷过榜,只是了解了一下,如现在的游戏、社交、旅游三个分类榜的前20名,几乎都靠刷榜刷进去的。刷进榜之后就维榜,冲分类榜前20名费用至少要5万,维榜费用每天至少要2万。冲免费榜前100名,费用就翻几倍了。现在刷榜维榜都是用积分墙,我觉得多盟、有米在闷声发大财。

      六、媒体推广

      说起这个就全是泪。我找了所有的科技博客,什么36氪、创业邦、快鲤鱼等等寻求报道,每个网站都有2个大大的按钮【求报道】、【投稿】,我既申请了报道也投了稿,过了3天石沉大海,然后我就继续申请,再过3天还是石沉大海。后来我在投资类的QQ群吐槽,群主说,你什么是见过他们网站报道融资100万的项目,别人融资100万都是对外宣传500万,你过几天等他们忘记了,就说自己融资了500万,肯定给你报道。恩,行,那我就等过几天他们忘记了再去求报道把。看来不吹牛不务虚是不行了。

      桔子科技觉得最好的推广办法还是应该集中兵力做应用市场推广,其他微博豆瓣微信做做品牌推广还不错,但下载转化率太低。个人最大的感悟就是,一定要把产品做好,让用户主动分享把产品到微博和朋友圈,推广起来就轻松,这个也是真正能免费长久带来的下载量。最好我也觉得一个不会吹牛不会刷榜的的推广人员肯定不是好员工。

      内容源于桔子科技,福建桔子信息科技有限公司桔子科技,移动互联,移动开发无线城市移动应用APPWebAPPAPP外包企业APPAPP推广手机软件开发高端品牌网站设计福州网络公司福建网站建设网络营销网站推广品牌建站高端建站软件开发空间租用域名注册专业服务商大型系统解决方案

      福建桔子信息科技有限公司--移动互联网全案服务商。致力于APP开发APP外包企业APPAPP推广手机软件开发APP制作,APP制作软件,APP定制,APP开发公司,APP公司,定位企业级应用以及视觉设计网络营销微信营销,。福州微信营销公司一切为了让您的生意更轻松!如您对我们桔子科技感兴趣,请登录微信营销官网oranllc.cn

    展开全文
  • (第APP测试篇)

    在这里插入图片描述

    第六章 App 测试

    在这里插入图片描述
    简述Android四大组件及生命周期

    Android 的四大组件包括:Activity、Service、BroadcasReceiver、ContentProvider在这里插入图片描述
    当点击 APP 图标启动程序,说明将要发生那些过程?

    1.点击桌面 app 图标,Launcher 进程采用Binder IPC 向 system_server 进程发起 startActivity 请求; 2.system_server 进程收到请求后,向 zygote 进程发送创建进程的请求(zygote 进程是Android 系统的
    第一个进程,zygote 意为受精卵,所有进程都是由它孵化而来)
    3.zygote 进程 fork 出新的子进程,即 App 进程;

    1. App 进程,通过Binder IPC 向 system_server 进程发起 attachApplication 请求system_server 进程收到请求后,进行一系列的准备工作,通过 Binder IPC 向 App 进程发送 scheduleLaunchActivity 请求
    2. App 的 binder 线程( Application Thread ) 在收到请求后, 通过 handler 向主线程发送 LAUNCH_ACTIVITY 消息
    3. 主线程收到Message 后,通过发射机制创建目标Activity,并回调 Activity.onCreate()方法在这里插入图片描述
      APP 测试的内容主要包括哪些,如何开展?

    功能测试:

    1.业务逻辑正确性测试:依据:产品文档->测试用例编写 兼容性测试:
    1.系统版本:Android:官方版本,定制版本;IOS:官方提供版本
    2.分辨率:720 * 1280 1080* 1920
    3.网络情况:2g 3g 4g 5g Wi-Fi异常测试

    1. 热启动应用:应用在后台长时间待机;应用在后台待机过程中,手机重启
    2. 网络切换和中断恢复:网络切换;中断恢复:
    3. 电话信息中断恢复 升级,安装,卸载测
      4.升级测试:临近版本升级(1.0->1.1);跨版本(1.0->…->2.2)
    4. 安装测试:首次安装;覆盖安装(同版本,不同版本覆盖);卸载后安装
    5. 卸载测试:首次卸载;卸载安装后在卸载健壮性测试
    6. 手机资源消耗:cpu,内存
    7. 流量消耗:图片,数据,视频
    8. 电量测试
    9. 崩溃测试在这里插入图片描述
      Android 的兼容性测试都考虑哪些内容?

    品牌机型兼容:根据市场占有率、发布时间等指标对主流、最新机型进行重点兼容

    ROM 兼容:需兼容原生的 ROM(2.1、2.2、2.3、4.0、4.1、4.2);第三方 ROM(小米、百度易、点心、魅族、阿里云……)

    屏幕兼容:需兼容 HVGA、VGA、WVGA、FWVGA、720p、1080p 屏幕分辨率,并考虑不同 PPI 的情况
    软件兼容:安全类软件(百度手机管家、360 优化大师、360 安全卫士、QQ 手机管家、安卓优化大师、网秦、LBE),输入法软件(系统自带、Sogou、百度)
    版本兼容:服务器端需要兼容产品早期版本所需的API 接口

    网络兼容:WiFi、3 大运营商的 2G,3G,4G 网络,需区分 WAP 和NET 接入在这里插入图片描述
    针对 App 的安装功能,写出测试点?

    • 安装

    1. 正常安装测试,检查是否安装成功。
    2. APP 版本覆盖测试。例如:先安装一个 1.0 版本的 APP,再安装一个高版本(1.1 版本)的 APP,检查是否被覆盖。
    3. 回退版本测试。例如:先装一个 2.0 版本的 APP,再安装一个 1.0 版本的 APP,正常情况下版本是可以回退的。
    4. 安装时内存不足,弹出提示。
    5. 根据安装手册操作,是否正确安装。
    6. 安装过程中的意外情况(强行断电、断网、来电话了、查看信息)等等,检查会发生的情况。
    7. 通过‘同步软件’,检查安装时是否同步安装了一些文件。
    8. 在不同型号、系统、屏幕大小、分辨率上的手机进行安装。
    9. 安装时是否识别有 SD 卡,并默认安装到 sd 卡中。
    10. 安装完成后,能否正常启动应用程序。
    11. 安装完成后,重启手机能否正常启动应用程序。
    12. 安装完成后,是否对其他应用程序造成影响。
    13. 安装完成后,能否添加快捷方式。
    14. 安装完成后,杀毒软件是否会对其当做病毒处理。
    15. 多进程进行安装,是否安装成功。
    16. 在安装过程中,所有的提示信息必须是英文或者中文,提示信息中不能出现代码、符号、乱码等。
    17. 安装之后,是否自动启动程序。
    18. 是否支持第三方安装。
    19. 在安装中点击取消

    • 卸载

    1. 用自己的卸载程序进行卸载,检查是否卸载干净。
    2. 用第三方工具,检查是否卸载干净。
    3. 在卸载过程中,点击取消按钮,看是否正常退出卸载程序,检查软件是否还能继续正常使用。
    4. 卸载过程中,出现意外(比如手机关机,没电,查看信息,接打电话),程序是否还能运行。
    5. 在卸载过程中,突然重启设备,再次访问程序,是否还能运行。
    6. 在没用使用程序时,删除目录文件,看程序是否能运行。
    7. 在使用过程中,直接删除目录文件,程序是否还能运行。
    8. 不同系统、硬件环境、网络环境下进行卸载。
    9. 卸载成功后,是否对其他程序有影响。
    10. 卸载后再次安装,是否正常使用。
    11. 在卸载过程中,所有的提示信息必须是英文或者中文,提示信息中不能出现代码、符号、乱码等。

    • 更新

    1. 当客户端有新版本时,提示更新。
    2. 非强制更新,可以取消更新,旧版本正常使用,下次使用软件时,仍然会出现更新提示。
    3. 强制更新,强制更新而用户没有更新时,退出客户端,下次启动,依然提示更新。
    4. 不卸载更新,检查是否可以更新。
    5. 不卸载更新,检查资源同名文件如图片等是否更新成最新版本。
    6. 非 wifi 网络下,提示是否更新,取消就加入待下载,wifi 下自动更新。在这里插入图片描述
      常用的 ADB 命令?

    adb --help / adb :看见帮助信息 adb start-server:启动 adb 服务adb kill-server:关闭 adb 服务 adb devices:查看手机设备号
    adb shell getprop ro.build.version.release:获取系统版本 adb push 电脑 手机
    adb pull 手机 电脑
    adb logcat | grep(unix) 包名 adb logcat | findstr(win) 包名
    adb shell :进入 shell 命令行,可以操作 Linux 命令
    adb shell dumpsys window windows | grep mFocusedApp:获取包名 启动名(win:adb shell dumpsys window windows | findstr mFocusedApp)
    adb install 路径/apk 文件:安装 apk 到手机上 adb uninstall 包名:卸载 app 从手机上
    adb shell am start -W 包名/启动名:app 启动时间

    在查看 logcat 命令日志时候怎么内容保存到本地文件?

    输出重定向:logcat >> log_file_name在这里插入图片描述
    App 崩溃(闪退),可能是什么原因导致的?

    缓存垃圾过多:由于安卓系统的特性,如果长时间不清理垃圾文件.会导致越来越卡.也会出现闪退情况. 运行的程序过多,导致内存不足

    应用版本兼容问题:如果应用版本太低,会导致不兼容,造成闪退。此外,有些新版本在调试中,也会造成应用闪退。解决方法:如果是版本太旧,更新为新版本即可;如果是新版本闪退,可能是应用在改版调试,可卸载后安装旧版。

    检查APP 中访问网络的地方,组件中的 ImageView 是否可以正常的下载并显示到 app 页面上。检查APP 的 sdk 和手机的系统是否兼容。

    在一些特定情况下的闪退,比如播放视频,在Android5.0 升级到Android6.0 的时候,有些系统 API 老版本有,新版本没有,到时回去对象的时候失败,报空,系统就会出现闪退问题.在这里插入图片描述
    如何测试监测 app 的内存使用、CPU 消耗、流量使用情况?

    adb shell top

    Android 应用性能测试通常包括:启动时间、内存、CPU、耗电量、流量、流畅度等根据手机的使用应用频度和强度不同,可将应用使用强度分为如下几种状态:
    • 空闲状态:指启动应用后,不做任何操作或切换到后台运行的情况称为空闲状态,该情况为应用对内存的消耗是最小的。
    • 中强度状态:该情况用户使用应用的强度和时间长短不确定,相对来说使用时长偏长。
    • 高强度状态:该种情况为应用内高频率的使用,用户很少达到,跑 monkey 时可认为高强度状态, 该种情况常用来测试应用内存泄漏的情况测试时,可根据用户的操作习惯模拟应用使用频率和强度等级。
    使用 adb 命令,手机连接电脑开启 USB 调试模式,进入 adbshell。

    1. 查看 CPU 占用率
      使用命令 top -m 10 -s cpu(-t 显示进程名称,-s 按指定行排序,-n 在退出前刷新几次,-d 刷新间隔,
      -m 显示最大数量),如下图:在这里插入图片描述
      参数含义:
      • PID:progressidentification,应用程序 ID
      • S: 进程的状态,其中 S 表示休眠,R 表示正在运行,Z 表示僵死状态,N 表示该进程优先值是负数。
      • #THR:程序当前所用的线程数
      • VSS:VirtualSet Size 虚拟耗用内存(包含共享库占用的内存)
      • RSS: ResidentSet Size 实际使用物理内存(包含共享库占用的内存)
      • UID:UserIdentification,用户身份 ID
      • Name:应用程序名称
      在测试过程中,QA 需要关注对应包的 cpu 占用率,反复进行某个操作,cpu 占用过高且一直无法释放, 此时可能存在风险。如果你想筛选出你自己的应用的话可以用下面命令 top -d 3| grep packageName在这里插入图片描述
    2. 查看内存使用情况
      dumpsys meminfo <package_name>或 dumpsys meminfo <package_id>在这里插入图片描述
      参数含义:
      • Naitve Heap Size: 从 mallinfo usmblks 获得,代表最大总共分配空间
      • Native Heap Alloc: 从 mallinfo uorblks 获得,总共分配空间
      • Native Heap Free: 从 mallinfo fordblks 获得,代表总共剩余空间
      • Native Heap Size 约等于Native Heap Alloc + Native Heap Free
      • mallinfo 是一个 C 库, mallinfo 函数提供了各种各样的通过 C 的 malloc()函数分配的内存的统计信息。
      • Dalvik Heap Size:从 Runtime totalMemory()获得,Dalvik Heap 总共的内存大小。
      • Dalvik Heap Alloc: Runtime totalMemory()-freeMemory() ,Dalvik Heap 分配的内存大小。
      • Dalvik Heap Free:从 Runtime freeMemory()获得,Dalvik Heap 剩余的内存大小。
      • Dalvik Heap Size 约等于Dalvik HeapAlloc + Dalvik Heap Free重点关注如下几个字段:
      • Native/Dalvik 的 Heap 信息中的 alloc :具体在上面的第一行和第二行,它分别给出的是 JNI 层和 Java 层的内存分配情况,如果发现这个值一直增长,则代表程序可能出现了内存泄漏。
      Total 的 PSS 信息:这个值就是你的应用真正占据的内存大小,通过这个信息,你可以轻松判别手机中哪些程序占内存比较大了。在这里插入图片描述
      弱网测试怎么测

    弱网环境测试主要依赖于弱网环境的模拟。环境搭建方式一般有两种:软件方式和硬件方式。软件方式的成本低,主要就是通过模拟网络参数来配置弱网环境,通常来讲可以达到测试目的.一般可通过热点共享设置。在各类网络软件中,主要就是对带宽、丢包、延时等进行模拟弱网环境。如果要求更接近弱网环境, 比如现在很多的专项测试,会更倾向于通过硬件方式来协助测试,但这种方式相对会麻烦很多,一般会由网维协助搭建。当然,对于有些无法模拟的情况,只能靠人工移动到例如电梯、地铁等信号比较弱的地方。
    “//*[contains(@text,”登录”)]”是什么意思
    定位第一个元素text 属性包含登录的元素
    Appium 都有哪些启动方式

    1. 客户端启动
    2. 命令行启动在这里插入图片描述
      如果对软件测试有兴趣,想了解更多的测试知识,解决测试问题,以及入门指导,帮你解决测试中遇到的困惑,我们这里有技术高手。如果你正在找工作或者刚刚学校出来,又或者已经工作但是经常觉得难点很多,觉得自己测试方面学的不够精想要继续学习的,想转行怕学不会的, 都可以加入我们**在这里插入图片描述
      **,群内可领取最新软件测试大厂面试资料和Python自动化、接口、框架搭建学习资料!

    测试新手

    如果你立志成为一名测试工程师,但却没有任何的知识储备。这时候,你应该抓紧时间学习计算机基础知识,同时,还需要了解编程体验、产品设计、用户体验和研发流程等知识。

    测试工程师
    从知识体系上看,你需要有更全面的计算机基础知识,还需要了解互联网的基础架构、安全攻击、软件性能、用户体验和常见缺陷等知识。从测试技术上看,你需要能够使用常见的测试框架或者工具,需要具有一定的自动化测试脚本的开发能力,

    高级测试工程师
    合格的测试工程师关注的是纯粹的测试,而优秀的测试工程师关注更多的是软件整体的质量,需要根据业务风险以及影响来制定测试策略。另外,优秀的测试工程师不仅可以娴熟地运用各类测试工具,还非常清楚这些测试工具背后的实现原理。

    测试架构
    测试架构师不仅仅应该有技术的深度,还应该有全局观。比如,面对大量测试用例的执行,无论是 GUI 还是 API,都需要一套高效的能够支持高并发的测试执行基础架构;再比如,面对测试过程中的大量差异性数据要求,需要统一的测试数据准备平台。同时,测试架构师还必须对一些前沿的测试方法和技术有自己的理解。

    展开全文
  • 基于多维度空间分配算法实现APP任务定价 基于多维度空间分配算法实现APP任务定价 摘要 一、问题重述 1.1 问题引言 1.2 题目数据及信息说明 1.3 提出问题 二、问题分析 2.1 问题的总体分析及思维导图 2.2 问题...

    基于多维度空间分配算法实现APP任务定价

    摘要

           本文是针对“拍照赚钱”APP任务定价问题进行分析,并采用多维度空间任务定价模型、会员抉择概率模型、项目总收益模型、入包威胁矩阵模型等对不同情况下的任务进行合理定价。
           针对问题一:首先对使用Geoq平台对任务以及会员数据进行定位,在这些数据中发现有部分的异常数据。在对异常数据进行删除处理之后使用任务-会员空间分布模型对其进行合理分配,从而进行数据整合操作,进而使用Python中的Matplotlib工具绘制多功能图来分析任务定价的规律以及部分任务未完成的原因,最终对任务定价数据进行指数拟合。
           针对问题二:在该问题中需要制定新的任务定价方案并与原方案进行比较。在完成任务一的前提下,我们首先使用Matlab工具并结合矩阵相关知识对任务-会员进行再次空间分配,之后使用Z-Score对数据进行标准化,进而逐步构建多维度空间任务定价模型、护院抉择概率模型、项目总收益模型来制定新的方案。我们得到结论:任务完成度提高了 12.005% 12.005 % ,项目实际收益提高了 18.3875% 18.3875 % ,总值为 42964 42964
           针对问题三:在考虑对任务进行打包的情况下,我们考虑到了会员信誉值和预定任务限额对任务定价的影响,对此构建入包威胁矩阵模型来对各项任务进行打包并将多维度空间任务定价模型进行有话啊,最终基于打包方案的优化模型制定新的方案,求解后得到结论:任务完成率再次提高了 9.341% 9.341 % ,收益率提高了 13.641% 13.641 % ,实际收益总值提高至 45163 45163

           针对问题四:

    关键词: 拟合、Geoq、Z-Score、Python、Matlab、入包威胁。

    一、问题重述

    1.1 问题引言

           随着互联网领域的快速发展以及人们对科学技术的不断创新,最近一款称为“拍照赚钱”的服务模式正在逐渐融入到人们的生活中。“拍照赚钱”是移动互联网下的一种新型的自助式服务模式。用户通过下载APP并且注册成为APP的会员之后,就可以在APP平台上领取需要拍照的任务(比如上超市去检查某种商品的上架情况),进而赚取APP对任务所标定的酬金。而这种基于移动互联网的自助式劳务众包平台相对于传统的市场调查方式来说,不仅为企业提供各种商业检查和信息搜集渠道,而且有效地保证了调查数据真实性,缩短了调查的周期,进而可以大大节省人力、物力、财力。因此APP成为该平台运行的核心,而会员接受任务的可能性主要由任务价格决定,故APP中的任务定价是核心要素,而且对于公司的来说起到一个决定性作用。如果任务定价不合理,有的任务就会无人问津,而导致商品检查的失败。相反,若能通过以往数据来对其进行合理性的建模从而确定任务的定价则会取得不凡的结果。

    1.2 题目数据及信息说明

           建模命题组给出的附件一是一个已结束项目的任务数据,其中包含了每个任务的所在地的经纬度、任务的标价以及任务的完成情况(“1”表示完成,“0”表示未完成);附件二则是会员的信息数据,其中包含了会员所在地的经纬度、预定任务的限额、预定任务的时间和会员所对应的信誉值,而信誉值往往是通过以往的任务完成情况所直接决定的,所以理论上说会员对应的信誉值越大,越优先开始挑选任务,其配额也就越大(任务分配时实际上是根据预订限额所占比例进行配发);附件三是一个新的检查项目任务数据,其中只有任务所在地的经纬度数据,我们要做的是通过给出的数据来建立一个或若干个模型,进而将此模型应用在这些新项目上从而给平台公司提供一个比较优秀的决策。

    1.3 提出问题

    • 研究附件一中项目的任务定价规律,分析任务未完成的原因。
    • 为附件一中的项目设计新的任务定价方案,并和原方案进行比较。
    • 实际情况下,多个任务可能因为位置比较集中,导致用户会争相选择,一种考虑是将这些任务联合在一起打包发布。在这种考虑下,如何修改前面的定价模型,对最终的任务完成情况又有什么影响?
    • 4.对附件三中的新项目给出你的任务定价方案,并评价该方案的实施效果。

    二、问题分析

    2.1 问题的总体分析及思维导图

           APP平台中任务定价的设计问题就是通过已完成任务的数据来合理有效的预测未完成任务的执行情况,并使得最终所有任务完成的总价格尽可能大,从而实现APP平台的最大价值率。对此,首先我们需要通过附录一和附录二中的数据来确定影响任务定价的可能相关因素以及分析最终未完成任务的可能原因,以便为后期的建模提供较优的铺垫;然后,在问题二中,我们需要在完成问题一的情况下,对该项目的任务设计一个新的定价方案并建立较优的数学模型,然后可以通过此模型来比较该新的设计方案与原方案的完成情况,进而总结改进之后方案的优点;此外,在问题三中,命题组提到多个集中的任务可能会对用户的选择造成影响,所以我们需要对之前的设计方案进一步通过将这些集中任务进行联合打包发布的方式来对模型进行优化,进而分析最终任务的完成情况;最后在问题四中,我们需要对通过前三问得出的模型来对附录三中的待定任务进行估价并且评价方案的实施效果。

    2.2 问题的具体分析

    2.2.1 问题一

           常言有道:具体问题具体分析。对于问题一来讲,我们可以将任务定价的影响因素归于两个方面,一种是已知提供的因素,另一种则是未知潜在的因素。在未知潜在的因素中有任务本身所对应的初始价值以及公司发布任务所在时间点的经营状况等方面因素决定,然而这些因素所决定的条件及信息我们无从得知,因此在这里我们在该论文中不做分析。而在已知提供的因素中,我们主要可以从命题组给出的附录中出发。在给出的附录一和附录二中,我们可以发现其中具有分析价值的数据,对此我们将影响任务的定价初步归因于任务的地理位置、会员所在地的集中程度、任务发布时间以及任务发布地的经济状况四个因素,后期我们也是从这四个因素出发来确定四个因素与任务定价的真正关系。而任务未完成的原因主要从任务定价的合理性、任务的竞争力两个方向进行分析。

    2.2.2 问题二

           “拍照赚钱”APP的任务定价是一种任务发布者(APP平台)与任务接受者(平台会员)之间所进行的互利模式,PP平台希望在成本一定的情况下使得任务的完成率尽可能的提高,而APP会员则需要在满足某种条件要求下追求收益尽可能大。从实际出发,一份任务理论上可以分配给多个使其相互竞争,而一个会员亦可接受多份任务,这两者在初始阶段是一种“多对多”的关系。而最终的情况是一个任务只能分配给一个会员,而一个会员依然可以接受多份任务,这是一种“多对一”的关系。

    2.2.3 问题三

           在本问中,提到实际情况下多个任务可能会因为位置比较集中而导致用户会争相选择,为此我们需要采用一种打包方式来对原方案进行优化。在采用任务打包方案之后之后虽然能够提高平台的任务发布效率,但是我们必须首先解决以下两个问题:

    • 制订一个合理的方案来对任务进行打包从而进一步提高任务的完成率,即每个打包任务簇中的任务数需要确定。

    • 任务簇中的任务数的确定由哪些因素决定

    2.2.4 问题四

    三、模型假设

    • 公司的在一定时间段内的经济状况保持水平。
    • 附件中任务的实际定价在进行任务-会员分配时保持不变。
    • 会员在完成任务过程中,不考虑有特殊情况从而导致会员终止任务的进行。
    • 会员的信誉值和预定任务的限额近似满足二维高斯分布。

    四、符号说明

    符号说明
    Dik D i k 任务 i i 与会员 k 的距离,单位千米(km)
    R R 地球的半径,单位千米(km)
    Pi任务 i i 的定价
    E(δ)某一城市的GDP所对应的经济系数
    Ci C i 会员的信誉值
    ρi ρ i 任务 i i 领域内的会员密度
    Qi任务 i i 领域内会员的竞争度
    Mk会员 k k 预定任务的限额
    θi任务 i i 的经度值
    φi任务 i i 的纬度值
    θk会员 k k 的经度值
    φk会员 k k 的纬度值

    说明:表中未提到的符号会在正文中作出解释。

    五、模型的建立与求解

    5.1 任务定价规律及未完成分析——问题一

    5.1.1 任务定价规律分析

    5.1.1.1 数据的整体定位

           首先我们需要对所有数据中的经纬度信息来进行定位,以便于我们后续的相关分析。在这里,我们选择使用智能GeoQ平台来对附录一和附录二中的数据进行定位以便我们后续的分析,一下是定位之后得到的结果图示:



    图二:附件一定位蓝黑版                                         图三:附件二定位蓝黑板



    图四:附件一定位彩色版                                         图五:附件二定位彩色版

           从定位之后的图示来看,我们可以不难发现以下两个结论:1.该数据主要收集于广东省的佛山市、广州市、东莞市、深圳市四个城市,后续我们也是针对这四个地区进行分析。2.这些数据中含有特殊值,这里我们将其视为异常值,需要进行特别处理。

    5.1.1.2 数据的预处理

           从我们所总结的因素出发,由于四个因素所在不同的附录之中,所以我们需要将这两个附录文件进行整合。首先通过附录一中的经纬度数据来确定任务的发布位置,然后由Python中的pandas和numpy两个工具包来对两个附录中的数据进行整合,进而完成该数据的预处理模块。

    5.1.1.2.1 附件一数据的预处理

           在附件一中,其内含有任务的相关经纬度数据,由于我们在分析任务定价的过程中,将任务发布的地理位置作为主要因素之一,故我们需要确定发布任务的位置与任务所在城市中心之间的距离,以此来具体确认任务定价与任务地理位置的关系。
           我们要想计算出任务点与中心位置的距离,则首先需要知道中心位置的经纬度。而由上述的数据定位可知,所有数据整体在佛山、广州、深圳、东莞四个城市中,据资料显示,这是个城市中心的经纬度如下所示:

    城市 经度 纬度
    广州 113.27 23.13
    佛山 113.12 23.02
    深圳 114.05 22.55
    东莞 113.75 23.05

           既然现在已知城市中心以及所有任务点的经纬度信息,我们即可通过以下式子计算出所有任务点与中心之间的距离:

    Dij=Rarccos[sinφisinφj+cosφicosφjcos(θiθj)]

    符号说明
    Dij D i j 任务 i i 与城市中心 j 的距离,单位千米(km)
    R R 地球的半径,单位千米(km)
    θi任务 i i 的经度值
    φi任务 i i 的纬度值
    θj城市 j j 的经度值
    φj城市 j j 的纬度值

           为此,我们就能由以下相关程序处理附件一中的数据:

    def append_length(file_path, jing_value2, wei_value2, file_name, encoding):
        df1 = pd.read_csv(file_path, encoding=encoding)
        length = []
        for index1, each_data1 in df1.iterrows():
            jing_value1 = each_data1["任务gps经度"]
            wei_value1 = each_data1["任务gps 纬度"]
            distance = int(6371 * np.arccos(np.sin(wei_value1)*np.sin(wei_value2)+np.cos(wei_value1)*np.cos(wei_value2)*np.cos(jing_value1-jing_value2)))
            length.append(distance)
        df1["与中心距离"] = length
        df1.to_csv(file_name, index=False)
    5.1.1.2.2 附件二数据的预处理

           在附录二中的会员数据里,我们发现其中的经纬度数据信息在同一字段中,为了分析的方便,我们首先使用pandas将该添加对应的经度和纬度两个字段,相关核心代码如下,完整代码可见附录:

    def deal_column(data_path, sheet):
        data = pd.ExcelFile(data_path)
        df = data.parse(sheet)
        locations = df["会员位置(GPS)"]
        location_jing = [location.split(" ")[1] for location in locations]
        location_wei = [location.split(" ")[0] for location in locations]
        df["会员gps经度"] = location_jing
        df["会员gps纬度"] = location_wei
        df.to_csv(d + "/after_deal.csv", index=False)

           处理之后的部分数据如下图所示:


    部分会员数据图

    图一:会员数据处理后的部分数据

    5.1.1.2.3 数据异常值的处理

           在上述操作中,我们发现附录一和附录二中含有异常值,我们需要针对进行异常值进行特殊处理,否则将会对我们后面的模型造成影响。要想具体确认每个经纬度所对应的具体位置,我们需要借助于GPSspg的相关操作。为此,我们首先将附件一和附件二中的各个位置的经纬度提取出来然后进行具体定位,最后导入到新的文件中,具体定位后的部分数据如下图所示:



    图六:具体定位部分数据

           通过文件中的数据可以发现,除了上述分析的佛山市、深圳市、广州市、东莞市之外还掺杂了其他地区的数据,例如清远市、中山市、别行政、惠州市等。经统计发现总共含有20个异常数据,它们的编号分别是A0297、A0751、B0005、B0006、B0007、B0022、B0033、B0039、B0048、B0082、B0135、B0136、B0472、B1077、B1585、B1627、B1708、B1727、B1820、B1822。它们的编号和具体数据内容可如图五、图六所示:



    图七:附件一中的异常数据                     图八:附件二中的异常数据

           为了不影响后面模型的精度,这里我们将这些异常数据进行直接进行删除即可,删除的部分核心代码如下所示:

    def delete_data(data_path, sheet):
        df = pd.read_csv(data_path)
        groups = df.groupby("城市")
        error_group = pd.DataFrame(columns=["会员编号","会员位置(GPS)","预订任务限额","预订任务开始时间","信誉值","会员gps经度","会员gps纬度","详细地址","城市"])
        true_group = pd.DataFrame(columns=["会员编号","会员位置(GPS)","预订任务限额","预订任务开始时间","信誉值","会员gps经度","会员gps纬度","详细地址","城市"])
        for city, group in groups:
            if city not in ["佛山市""广州市""深圳市""东莞市"]:
                error_group = pd.concat([error_group, group])
            else:
                true_group = pd.concat([true_group, group])
        error_group.to_csv("error_data.csv", index=False)
        true_group.to_csv("true_data.csv", index=False)
    5.1.1.2.4 数据的整合

           由之前对任务定价的分析可知,我们需要将会员数据与任务数据进行整合,从而进一步分析公司在对任务定价的时候是否考虑到会员的相关因素。在此,我们将两个附件的数据进行整合操作的依据是在一定区域范围之内所含有的会员数目,并以此求相关会员信息的均值来对定价进行分析。我们可以通过以下公式进行计算:

    Dik=Rarccos[sinφisinφk+cosφicosφkcos(θiθk)]

    符号说明
    Dij D i j 任务 i i 与会员 k 的距离,单位千米(km)
    R R 地球的半径,单位千米(km)
    θi任务 i i 的经度值
    φi任务 i i 的纬度值
    θk会员 k k 的经度值
    φk会员 k k 的纬度值

           通过上述距离公式,我们可以借助numpy工具计算每个任务在与会员之间的距离是否在我们规定的范围之内,从而将附件二中的有效数据合并到附件一中,即在附件一中添加四个字段:会员预定任务的限额、会员所在地的集中程度、任务发布时间以及任务发布地的经济状况。其中前三个因素可以在附录一中进行算法提取,而为了分析问题的全面性,这里多考虑到了任务发布地区的经济状况因素,虽然在本题中并未给出该方面的数据,但是我们可以通过查找相关资料进行了解从而进行综合性分析。
           通过上述的分析,我们在这规定若任务与会员之间的距离小于 r ,则我们将该会员的数据录入到对应的任务中,即:

    r>Dik=Rarccos[sinφisinφk+cosφicosφkcos(θiθk)] r > D i k = R ∗ a r c c o s [ s i n φ i ∗ s i n φ k + c o s φ i c o s φ k c o s ( θ i − θ k ) ]

           结合实际情况与各个数据的经纬度的联系,我们在对数据进行整合的时候取 r=500km r = 500 k m 。由于该部分的核心代码较长,出于对论文可读性的考虑,此部分的代码不在此处进行展示,读者可在附录中进行浏览。整合之后的部分相关数据如下:



    5.1.1.3 定价规律可视化及分析
    5.1.1.3.1 任务的地点位置对定价的影响分析

           为了分析出任务点位置对任务定价的具体影响,我们需要将上述预处理之后的附件一中的数据进行可视化从而得到任务位置对任务定价的影响。为此我们将任务 i i 定为 Pi ,将任务点与城市中心的距离定为 Dij D i j ,通过这两个数据便可绘制两者之间的关系图。此处,我们不妨使用散点图将每个数据点在直角坐标系中表示出来,从而分析任务定价随着任务位置之间的大致趋势,进而选择恰当的函数来对数据点进行拟合。除此之外,为了避免城市的不同而对任务价格的影响,我们分别绘制广州、佛山、深圳、东莞的定价位置散点图。基于这种分析,我们使用matplotlib工具绘制出的散点图以及程序的核心代码如下:

    def draw_scatter(file_path, color, marker, city, image_path):
        df = pd.read_csv(file_path)
        p = df["任务标价"]
        d = df["与中心距离"]
        plt.scatter(d/100, p, s=10, c=color, alpha=0.6, marker=marker)
        plt.title("{}任务位置与定价的关系".format(city), fontproperties=font)
        plt.xlabel("Distance/x100km")
        plt.ylabel("Price")
        plt.savefig(image_path)
        plt.show()





           从上面的任务定价与任务位置之间的散点图中不难发现,深圳、广州、东莞、佛山整体呈现一种 “上疏下密,右疏左密”的形式。故于此,我们可以得到以下结论:距市中心越进的任务,APP平台对其任务定价相对比较低,定价在65~75之间;而距市中心越远的任务,APP平台对其任务定价相对较高,定价在76~86之间。此外,随着距离的增大,定价的价格增长的幅度整体在逐渐增大。对此,我们将这两种模型近似拟合为一个指数回归模型。
           所以,根据上面所述,我们不妨建立一个关于任务点位置对任务定价的影响的模型,为了模型进行的精确性以及拟合效果的良好度,这里我们利用WPSExcel中的散点指数拟合模型进行拟合,且该模型满足以下关系式:

    Pi=66.892e35Dij P i = 66.892 ∗ e 3 − 5 D i j

           至此,我们已经求解出任务位置与定价的数学模型,而为了确认该模型的拟合程度,我们需要引入拟合优度值 r2 r 2 来进一步验证该模型。

    r2=1mi=0(PiPc)mi=0(PiP¯¯¯¯) r 2 = 1 − ∑ i = 0 m ( P i − P c ) ∑ i = 0 m ( P i − P ¯ )

           通过科学计算可得知拟合优度 r2 r 2 =0.7317295,该值近似为1可知,该模型的拟合具有比较好的效果。于此,我们可以确认任务的位置与任务的定价存在较大的关系,即距市中心越进的任务,APP平台对其任务定价相对比较低,定价在65~75之间;而距市中心越远的任务,APP平台对其任务定价相对较高,定价在76~86之间。
           通过结合现实来讲,存在这种定价规律主要存在以下原因:

    • 在距城市中心较近处,具有较大的人口密度且较为发达,完成任务的可能性较大,所以公司为了提高任务的完成率需要增大会员对任务的渴求欲,任务的价格普遍较低。
    • 在距城市中心较远处,地理位置比较偏僻且周围环境相对比较恶劣,完成任务的可能性比较小,所以公司进行提高任务定价的方式来诱导会员完成任务。

           随后,通过我们上面所描述,任务点的经纬度与城市中心满足以下关系:

    Dij=Rarccos[sinφisinφj+cosφicosφjcos(θiθj)] D i j = R ∗ a r c c o s [ s i n φ i s i n φ j + c o s φ i c o s φ j c o s ( θ i − θ j ) ]

           所以,最终我们将任务的定价与任务的经纬度的关系模型定义如下:

    Pi=66.892e35Rarccos[sinφisinφj+cosφicosφjcos(θiθj)] P i = 66.892 ∗ e 3 − 5 R ∗ a r c c o s [ s i n φ i s i n φ j + c o s φ i c o s φ j c o s ( θ i − θ j ) ]

    5.1.1.3.2 任务发布地的经济状况

           除了任务距城市中心的距离对任务的定价造成影响之外,城市的经济状况也会对其产生一定的影响。而为分析此种影响,我们需要对以上所述的四个城市的经济状况有所了解。据资料显示,四个城市的GDP以及变化率如下所示:

    城市GDP变化情况
    深圳19492.60亿增长:9.38%
    广州19610.94亿增长:8.34%
    佛山8003.92亿增长:7.16%
    东莞6275.06亿增长:6.69%

           之后,我们通过matplotlib来绘制四个城市的任务平均价格关系图,相关程序及图示结果如下所示:

    def get_mean_price(file_path):
        df = pd.read_csv(file_path)
        p = df["任务标价"]
        mean_price = np.mean(p)
        return mean_price
    
    if __name__ == "__main__":
        files = [parent_path + "/newdata/cleaneddata/final_data1_sz.csv", parent_path + "/newdata/cleaneddata/final_data1_gz.csv", parent_path + "/newdata/cleaneddata/final_data1_fs.csv", parent_path + "/newdata/cleaneddata/final_data1_dg.csv"]
        price_ls = [get_mean_price(each_file) for each_file in files]    
        plt.barh(np.arange(4), price_ls, height=0.7, color="lightskyblue")
        plt.xlabel("Price")
        plt.ylabel("Cities")
        plt.title("城市与任务定价的关系", fontproperties=font)
        plt.yticks(np.arange(4), ["深圳", "广州", "佛山", "东莞"], rotation=45, size=8)
        for x, value in enumerate(price_ls):
            plt.text(y=x, x=value, s="{}".format(value), ha="center", )
        plt.savefig(parent_path + "/images/city_price.jpg")
        plt.show()



           从图中我们可以了解到,东莞与佛山的任务定价相对较高,而广州和深圳的任务定价相对较低。这与上述各个城市的经济状况正好呈现一种相反的趋势,这种趋势理解为城市的经济状况与任务定价成负相关。

    5.1.1.3.3 会员所在地的集中程度

           从实际出发,公司在给任务进行定价的时候,一般会考虑到一定区域内会员的分布密度,且在分布密度较小的区域内公司会提高任务的定价,以此来吸引更多的会员,从而提高APP平台访问的用户量,进而使公司的利益最大化。为此,我们同样需要由整合之后的数据来分析会员集中度对任务定价的影响,最终实现的效果图如下所示:



    回溯胡

           由上图我们可以看出,结果与我们料想的如出一辙。会员的集中度与任务的定价整体存在某种负相关关系。

    5.1.2 任务未完成原因分析

    5.1.2.1 任务未完成数据处理

           在进行分析任务未完成原因分析时,首先我们需要对任务未完成的数据进行处理,该处理部分我们主要通过任务未完成任务数据的提取来进行。相关处理核心代码如下:

    def split_yes_no(file_name1, file_name2):
        df = pd.read_csv(data_path6, encoding="gbk")
        for status, group in df.groupby("任务执行情况"):
            if status == 0:
                group.to_csv(file_name1, index=False)
            else:
                group.to_csv(file_name2, index=False)

           在分解之后,我们发现未完成的任务数据有313组,后面我们将针对这313组的数据进行原因分析。

    5.1.2.2 任务的定价过低

           首先,我们不难发现,若公司对一组任务的定价过低,则定价很大可能不足以引起会员的接单欲望。所以,任务的定价过低很有可能是造成任务未完成的原因之一。
           通过对数据的观察我们可以发现,任务的定价皆在65~85之间。为此,我们将任务分为四个定价区间,即65~69、70~74、75~79、80~85四个数据区域。通过此分析,我们可以绘制数据的散点图以及他们的相关统计图,相关核心代码以及结果图示如下:

    def draw_no_scatter():
        df = pd.read_csv(parent_path + "/newdata/no.csv")
        plt.scatter(np.arange(313), df["任务标价"], s=20, c="red", alpha=0.6, marker="*")
        plt.title("任务未完成数据的价格分布")
        plt.xlabel("Mission")
        plt.ylabel("Price")
        plt.savefig(parent_path + "/images/no_price.jpg")
        plt.show()
    def draw_no_bar():
        df = pd.read_csv(parent_path + "/newdata/no.csv")
        df1 = df[(65 <= df["任务标价"]) & (df["任务标价"] < 70)]
        df2 = df[(70 <= df["任务标价"]) & (df["任务标价"] < 75)]
        df3 = df[(75 <= df["任务标价"]) & (df["任务标价"] < 80)]
        df4 = df[(80 <= df["任务标价"]) & (df["任务标价"] < 85)]
        data_len = [len(df1), len(df2), len(df3), len(df4)]
        plt.barh(np.arange(4), data_len, height=0.6, alpha=0.7, color="yellowgreen")
        plt.ylabel("Price Region")
        plt.xlabel("Num")
        plt.title("未完成价格条形图")
        plt.yticks(np.arange(4), ["65-69", "70-74", "75-79", "80-85"], rotation=45, size=13)
        for x, value in enumerate(data_len):
            plt.text(y=x, x=value, s="{}".format(value), ha="center")
        plt.savefig(parent_path+"/images/price_bar.jpg")
        plt.show()
    
        plt.pie(x=data_len, labels=["65-69", "70-74", "75-79", "80-85"], autopct="%.0f%%", shadow=True, radius=1.2)
        plt.legend(["65-69", "70-74", "75-79", "80-85"], loc="best")
        plt.title("未完成价格饼图")
        plt.savefig(parent_path+"/images/price_pie.jpg")
        plt.show()



           通过以上图的显示,我们在散点图中可以明显的看出任务定价在65-75的区间内明显占据绝大部分。从条形图和饼图中我们也能看出其所占比例之大。为此,我们可以确定之前的结论,即公司对任务定价过低的时候,不足以勾起会员完成任务的欲望,也就是说会员完成任务的可能性极小。

    5.1.2.3 任务发布位置较远

           在原因一的分析中,除了任务定价在65-75之间之外,还有23组的任务的定价相对来说是比较高的。那么既然如此,会员未完成任务的原因是什么呢?为此,我们在这需要分析任务是否离城市中心的距离较远,从而导致会员完成任务的难度增大。

    5.1.3 问题一总结

           通过以上模块的分析,我们得出公司对任务定价主要从任务点位置、任务发布地的经济状况、会员预定任务限额、信誉值、集中度所决定。而任务未完成的原因主要是任务的定价较低以及任务较远导致。

    5.2 多维度定价方案对项目的效益——问题二

           “拍照赚钱”APP的任务定价是一种任务发布者(APP平台)与任务接受者(平台会员)之间所进行的互利模式,PP平台希望在成本一定的情况下使得任务的完成率尽可能的提高,而APP会员则需要在满足某种条件要求下追求收益尽可能大。在问题二中,要求为项目设计新的任务定价方案,则需要考虑以下几个方面:

    • 该项目的总收益由两个因素决定,一是任务的实际定价,二是任务的实际完成情况。
    • 站在公司的角度考虑,任务的定价是由平台根据相关数据而定的,而任务的定价在问题一中我们已做分析,影响任务定价的因素有该区域会员的信誉值、会员预定任务限额、会员与任务之间的距离、该区域的经济发展状况以及会员的集中密度。
    • 站在会员的角度分析,任务的完成率由会员根据实际情况而定,而对任务完成率的影响因素主要有,任务的价格、会员与任务之间的距离以及该任务的竞争程度。

           除此之外,从实际出发,一份任务理论上可以分配给多个使其相互竞争,而一个会员亦可接受多份任务,这两者在初始阶段是一种“多对多”的关系。而最终的情况是一个任务只能分配给一个会员,而一个会员依然可以接受多份任务,这是一种“多对一”的关系。通过以上对该问题的分析,我们可以构建项目-会员-任务之间的关系图:

           通过上述的分析,对此本文主要从以下四个步骤进行解决该问题:

    Step1. 确定任务-会员空间分配算法
    Step2. 由问题一分析出的多因素对任务定价造成的影响,建立出多维度空间任务定价模型。
    Step3. 对任务完成度进行分析并构建会员抉择概率模型。
    Step4. 通过上述模型的构建最终确定能够体现出新方案效果的项目总收益模型。
    Step5. 使用Matlab、Python、Lingo三种编程语言来对模型进行求解并总结新方案的优势。

    5.2.1 模型构建

    5.2.2.1 任务-会员空间分配

           首先,我们需要一个算法来对任务、会员之间进行合理的分配,以便后续模型的构建。出于体现出全国大学生数学建模竞赛的创新性,以下给出该任务-会员空间分配算法的实现流程图:



    任务-会员距离矩阵:
           用 xi x i 表示第 i(i=1,2,,n) i ( i = 1 , 2 , ⋯ , n ) 个任务, yj y j 表示第 k(k=1,2,,m) k ( k = 1 , 2 , ⋯ , m ) 个会员。以任务为节点,任务与每位会员之间的距离为对应的权重,为此构建该城市的任务-会员距离矩阵 L(δ)(δ=1,2,3,4) L ( δ ) ( δ = 1 , 2 , 3 , 4 ) ,如下所示:

    L(δ)=(D(δ)ik)n×m=D(δ)11D(δ)21D(δ)31D(δ)n1D(δ)12D(δ)22D(δ)32D(δ)n2D(δ)13D(δ)23D(δ)33D(δ)n3D(δ)1mD(δ)2mD(δ)3mD(δ)nm(5)(6) (5) L ( δ ) = ( D i k ( δ ) ) n × m (6) = ( D 11 ( δ ) D 12 ( δ ) D 13 ( δ ) ⋯ D 1 m ( δ ) D 21 ( δ ) D 22 ( δ ) D 23 ( δ ) ⋯ D 2 m ( δ ) D 31 ( δ ) D 32 ( δ ) D 33 ( δ ) ⋯ D 3 m ( δ ) ⋮ ⋮ ⋮ ⋱ ⋮ D n 1 ( δ ) D n 2 ( δ ) D n 3 ( δ ) ⋯ D n m ( δ ) )

    D(δ)ik=Rarccos[sinφisinφk+cosφicosφkcos(θiθk)] D i k ( δ ) = R ∗ a r c c o s [ s i n φ i ∗ s i n φ k + c o s φ i c o s φ k c o s ( θ i − θ k ) ]

    5.2.2.2 多维度空间任务定价模型

           通过问题一的分析,我们已经知道了多因素对任务定价产生的影响规律,主要体现在以下多个方面:

    • 在以某个任务为中心的一定区域内,若该区域中的会员信誉值较小时,则该任务的定价普遍较低。
    • 随着会员离任务的距离逐渐增大,则任务的定价普遍按照一定的波动规律有所提高。
    • 若城市的经济状况较为发达,则该城市的任务定价相对较低。
    • 如若会员的集中密度逐渐增大,则任务的定价按照一定趋势有所下降。

           在上一模块中,我们已经通过任务-会员空间分配模型分别对任务分配了相对应的会员量,并将其距离数据存储于矩阵 Lδ L δ 中,但为了避免影响其他因素之间复杂的相关性以及给模型求解带来一定的难度,我们首先需要使用 Zscore[1] Z − s c o r e [ 1 ] 模型对矩阵中数据进行归一化处理:

    D(δ)ik=D(δ)ikμσ D i k ( δ ) ∗ = D i k ( δ ) − μ σ

    σ=1n×mi=1nk=1m(D(δ)ikμ)2 σ = 1 n × m ∑ i = 1 n ∑ k = 1 m ( D i k ( δ ) − μ ) 2

    μ=1n×mi=1nk=1mD(δ)ik,  μ = 1 n × m ∑ i = 1 n ∑ k = 1 m D i k ( δ ) ,  

    L(δ)=(D(δ)ik)n×m L ( δ ) ∗ = ( D i k ( δ ) ∗ ) n × m

           同理,我们可以对矩阵中所对应会员的信誉值做归一化处理。通过上述分析,为此,我们可以构建多维度空间任务定价模型:

    Pi=KE(δ)(K1Ci¯¯¯¯¯ρi)a+(K2Di¯¯¯¯¯¯ρi)aa+ξ P i = K E ( δ ) ( K 1 C i ¯ ρ i ) a + ( K 2 D i ¯ ρ i ) a a + ξ

    Ci¯¯¯¯¯=1mk=1mck, Di¯¯¯¯¯¯=1mk=1mDik C i ¯ = 1 m ∑ k = 1 m c k ,   D i ¯ = 1 m ∑ k = 1 m D i k

           其中, Ci¯¯¯¯¯ C i ¯ 表示该任务点所在领域内会员信誉期望值, Di¯¯¯¯¯¯ D i ¯ 表示任务点所在领域内会员位置期望值, E(δ) E ( δ ) 表示任务所在城市的经济系数, ρi ρ i 表示任务所在领域内会员密度值, K,K1,K2 K , K 1 , K 2 表示价格与多维度因素之间的比例系数, ξ ξ 表示该方案的容错误差值。

           同时,我们可以通过上述四个城市的GDP(国内生产总值)来确定该模型的经济系数 E(δ) E ( δ )

    城市深圳广东佛山东莞
    E(δ) E ( δ ) 1.9492601.9610940.8003920.627506

           最终,确定的多维度空间任务定价模型如下:

    Pi=KE(δ)(K11mρik=1mck)a+(K21mρik=1mDik)aa+ξ P i = K E ( δ ) ( K 1 1 m ρ i ∑ k = 1 m c k ) a + ( K 2 1 m ρ i ∑ k = 1 m D i k ) a a + ξ

    5.2.2.3 会员抉择概率模型

           同样,在上述的分析中,我们已经把影响任务完成度的因素归结于任务的定价、任务位置、任务竞争度。且这三种因素的影响如下:

    • 若某一任务的定价较高时,任务对会员的吸引度较大,该任务被完成的概率也随之增大。
    • 从实际出发,若任务离会员越远,任务对会员的吸引度越小,该任务被完成的概率也随之减小。
    • 若一任务的会员竞争度较大,即该会员被较多的会员相中,相应的任务被完成的概率较高。

           首先,任务完成与否是由会员对任务所能获得期待的效益决定,当该效益值达到一定的阈值时,我们可以认为该任务被领域内的会员完成的概率较高,对此,我们应该建立该任务-会员吸引度模型:

    A=λPiQiDi¯¯¯¯¯¯ A = λ P i Q i D i ¯

           其中, Qi Q i 表示任务的竞争度,在这里我们可以将上述任务-会员矩阵中每行的会员数。根据实际情况,我们认为若一个任务的定价小于70,归一化后的距离大于0.8,被相中的会员数小于3,我们任务该任务完成的概率为0,其所对应的任务对会员的吸引度为 A110 A 1 ≤ 10 ;同样若某个任务的定价大于80,归一化后的距离小于0.2,被相中的会员数大于8,我们认为该任务被完成的概率为1,其所对应的任务吸引度为 A190 A 1 ≥ 90 。根据上述信息,我们可以确定 λ λ 的值:

    λ=12(A1D1i¯¯¯¯¯¯P1iQ1i+A2D2i¯¯¯¯¯¯P2iQ2i) λ = 1 2 ( A 1 D i 1 ¯ P i 1 Q i 1 + A 2 D i 2 ¯ P i 2 Q i 2 )

           经计算, λ=0.042634 λ = 0.042634 。对此,我们可以确定任务-会员吸引度模型最终为:

    A=A1,0.042634PiQiDi¯¯¯¯¯¯,A2,Pi<70,Qi<3,Di¯¯¯¯¯¯>0.8othersPi>80,Qi>8,Di¯¯¯¯¯¯<0.2 A = { A 1 , P i < 70 , Q i < 3 , D i ¯ > 0.8 0.042634 P i Q i D i ¯ , o t h e r s A 2 , P i > 80 , Q i > 8 , D i ¯ < 0.2

           根据任务-会员吸引度模型,我们可以建立出会员抉择概率模型:

    Zi=0,0.042634PiQi100×Di¯¯¯¯¯¯,1,0.042634PiQiDi¯¯¯¯¯¯<10100.042634PiQiDi¯¯¯¯¯¯<900.042634PiQiDi¯¯¯¯¯¯90 Z i = { 0 , 0.042634 P i Q i D i ¯ < 10 0.042634 P i Q i 100 × D i ¯ , 10 ≤ 0.042634 P i Q i D i ¯ < 90 1 , 0.042634 P i Q i D i ¯ ≥ 90

    Pi=KE(δ)(K11mρik=1mck)a+(K21mρik=1mDik)aa+ξ 其 中 , P i = K E ( δ ) ( K 1 1 m ρ i ∑ k = 1 m c k ) a + ( K 2 1 m ρ i ∑ k = 1 m D i k ) a a + ξ

    5.2.2.4 项目总收益模型

           我们已经分析得到项目的总收益是由任务定价以及任务的完成情况而定,而在上面我们确定了任务多维度空间任务定价模型和会员抉择概率模型,由此,我们可以构建出项目总收益模型,以分析出新方案的实施效果,项目的总收益根据会员抉择概率模型可分为三个部分:不可能收益、绝对收益、概率收益。其一般式如下:

    W(δ)=i=1nPiZi=W1+W2+W3=0+1lPi+i=lnPiZi(7)(8) (7) W ( δ ) = ∑ i = 1 n P i Z i = W 1 + W 2 + W 3 (8) = 0 + ∑ 1 l P i + ∑ i = l n P i Z i

           之后,将上述的任务多维度空间定价模型和会员抉择概率模型代入其中,可最终确定项目总收益模型:

    W(δ)=i=1l(KE(δ)(K11mρik=1mck)a+(K21mρik=1mDik)aa+ξ)+i=ln0.042634QiDi¯¯¯¯¯¯(KE(δ)(K11mρik=1mck)a+(K21mρik=1mDik)aa+ξ)2(9)(10) (9) W ( δ ) = ∑ i = 1 l ( K E ( δ ) ( K 1 1 m ρ i ∑ k = 1 m c k ) a + ( K 2 1 m ρ i ∑ k = 1 m D i k ) a a + ξ ) (10) + ∑ i = l n 0.042634 Q i D i ¯ ( K E ( δ ) ( K 1 1 m ρ i ∑ k = 1 m c k ) a + ( K 2 1 m ρ i ∑ k = 1 m D i k ) a a + ξ ) 2

    5.2.2 模型求解

           首先,我们需要通过上述的任务-会员分配算法对任务、会员之间进行分配,部分程序代码和分配结果如下:

    [a, b] = size(data1_dg_jing);
    [c, d] = size(data2_dg_jing);
    mt_data = zeros(a,c);
    for i = 1:a
        for j = 1:c
            mt_data(i,j) = 6371*acos(sin(data1_dg_wei(i))*sin(data2_dg_wei(j))+cos(data1_dg_wei(i))*cos(data2_dg_wei(j))*cos(data1_dg_jing(i)-data2_dg_jing(j)));
        end
    end
    normalized_data = zscore(mt_data);
    for i = 1:a
        for j = 1:c
            if normalized_data(i,j) > 0
                normalized_data(i,j) = 0;
            end
        end
    end

           通过上述对任务-会员进行分配之后,我们可以使用Matlab进行网格搜索来确定各个需要的系数值,最终我们可以将多维度空间任务定价模型定义如下:

    Pi=0.6359E(δ)(3.83741mρik=1mck)2+(5.69131mρik=1mDik)2±5 P i = 0.6359 E ( δ ) ( 3.8374 1 m ρ i ∑ k = 1 m c k ) 2 + ( 5.6913 1 m ρ i ∑ k = 1 m D i k ) 2 ± 5

    E(δ)=1.949260,1.961094,0.800392,0.627506 E ( δ ) = 1.949260 , 1.961094 , 0.800392 , 0.627506

           而会员抉择概率模型我们在上面已经进行分析,其与任务定价、距离、竞争有关,对此我们同样可以确定最终的会员抉择概率模型并进一步求解项目总收益模型:

    W(δ)=i=1l(0.6359E(δ)(3.8374Ci¯¯¯¯¯ρi)2+(5.6913Di¯¯¯¯¯¯ρi)2±5)+i=ln0.042634QiDi¯¯¯¯¯¯(0.6359E(δ)(3.8374Ci¯¯¯¯¯ρi)2+(5.6913Di¯¯¯¯¯¯ρi±5)2(11)(12) (11) W ( δ ) = ∑ i = 1 l ( 0.6359 E ( δ ) ( 3.8374 C i ¯ ρ i ) 2 + ( 5.6913 D i ¯ ρ i ) 2 ± 5 ) (12) + ∑ i = l n 0.042634 Q i D i ¯ ( 0.6359 E ( δ ) ( 3.8374 C i ¯ ρ i ) 2 + ( 5.6913 D i ¯ ρ i ± 5 ) 2

           其对应的优化模型如下:

    max δ=14W(δ)s.t.min(C1,C2,,Ci)Ci¯¯¯¯¯max(C1,C2,,Ci)min(D1,D2,,Di)Di¯¯¯¯¯¯max(D1,D2,,Di)i=1,2,,n m a x   ∑ δ = 1 4 W ( δ ) s . t . { m i n ( C 1 , C 2 , ⋯ , C i ) ≤ C i ¯ ≤ m a x ( C 1 , C 2 , ⋯ , C i ) m i n ( D 1 , D 2 , ⋯ , D i ) ≤ D i ¯ ≤ m a x ( D 1 , D 2 , ⋯ , D i ) i = 1 , 2 , ⋯ , n

           对于该最优化模型,我们使用Lingo对其进行求解,之后使用新方案对附件一中的任务数据进行处理,最终获得的结果部分如下所示:

    5.2.3 模型求解分析与问题总结

           通过上述的模型构建以及模型求解,我们制订了任务定价的新方案,而且对于新方案,其优势可以由以下几个方面总结:

    • 在任务完成方面,原方案中含有313个未完成任务,而在使用新方案之后任务未完成数减少到213个,其任务完成率从 62.425% 62.425 % 提高到了 74.430% 74.430 % ,新方案对任务完成情况的优化程度为 12.005% 12.005 %

    • 在项目实际收益方面,原方案的实际收益为 36291 36291 ,新方案的实际收益为 42964 42964 ,收益率提高了 18.3875% 18.3875 %

    • 在项目的理想收益方面,原方案该项目的理想收益为 57552.5 57552.5 ,而在使用了新方案之后,该项目的理想收益是 54319 54319

           综上所述,我们所制订的新方案一方面能够让APP平台的收益有个较大的提高,另一方面同时能够使会员的收入有所增多,即在APP平台和会员之间实现了双赢的效果,在双方获利的同时还有利于之间的长期合作。

    5.3 基于打包方案的优化——问题三

           在本问中,提到实际情况下多个任务可能会因为位置比较集中而导致用户会争相选择,为此我们需要采用一种打包方式来对原方案进行优化。在采用任务打包方案之后之后虽然能够提高平台的任务发布效率,但是我们必须首先解决以下两个问题:

    • 制订一个合理的方案来对任务进行打包从而进一步提高任务的完成率,即每个打包任务簇中的任务数需要确定。

    • 任务簇中的任务数的确定由哪些因素决定

    5.3.1 基于打包方案的优化模型建立及求解

           在问题二的多维度空间任务定价模型、会员抉择概率模型、项目收益模型中,他们之间是一种环环相扣的关系。而打包任务定价模型是建立在多位度空间任务定价模型的基础上的,所以我们优化的主要模型是多维度空间任务定价模型,继而改变打包任务的定价来体现出优化方案的优势。

    1) 会员信誉值及预定任务限额分析

           结合实际情况,从APP平台的角度分析,打包任务的任务数是由该打包区域中的所有会员的信誉值和预定任务的限额所决定。为此,我们需要进一步分析会员信誉值和预定任务限额的分布规律。
           要想了解会员预定任务的限额以及信誉值对任务定价的影响,我们首先需要用matplotlib绘图工具分别绘制以下两种因素对定价的影响:



           由上述图示我们可以知道,数据点主要集中在图示的左下端部分,即在会员信誉值及预定任务额较低的时候,任务的定价普遍较低;反之,任务定价相对较高。
           为了避免影响其他因素之间复杂的相关性以及给模型求解带来一定的难度,我们首先需要对会员信誉值 Qk Q k 和预定任务限额 Mk M k 进行标准化处理:

    Qk=Qkμσ Q k ∗ = Q k − μ σ

    σ=1mk=1m(Qkμ)2,  μ=1mk=1mQk σ = 1 m ∑ k = 1 m ( Q k − μ ) 2 ,     μ = 1 m ∑ k = 1 m Q k

           通过统计我们发现,会员信誉值和预定任务限额呈现一种“中间高,两头低”的特征。对此,我们认为会员的信誉值和预定任务限额满足二维高斯分布 [2] [ 2 ] ,其概率密度函数如下所示:

    f(Qk,Mk)=12πσ1σ21ρ2e12(1ρ2)((Qkμ1)2σ21+2ρ(Qkμ1)(Mkμ2)σ1σ2+(Mkμ2)2σ22) f ( Q k ∗ , M k ∗ ) = 1 2 π σ 1 σ 2 1 − ρ 2 e − 1 2 ( 1 − ρ 2 ) ( ( Q k ∗ − μ 1 ) 2 σ 1 2 + 2 ρ ( Q k ∗ − μ 1 ) ( M k ∗ − μ 2 ) σ 1 σ 2 + ( M k ∗ − μ 2 ) 2 σ 2 2 )

           其中, μ1,μ2,σ1,σ2,ρ μ 1 , μ 2 , σ 1 , σ 2 , ρ 都是常数,我们把该分布记作 N(μ1,μ2,σ1,σ2,ρ) N ( μ 1 , μ 2 , σ 1 , σ 2 , ρ )

    2)打包方案任务定价模型

           在确定了会员信誉值和预定任务限额的分布以及对任务定价影响规律之后,我们需要建立打包方案的任务定价模型。当概率 f(Qk,Mk) f ( Q k ∗ , M k ∗ ) 达到一定值时,我们可以认为该会员对任务的影响较大,即某任务簇中的任务数较多,入包的可能性较大,对此,我们先建立一个任务入包威胁矩阵模型

    J=(Ri)a×b J = ( R i ) a × b

           其中, a a 表示最终打包的任务簇数,b 表示附件二中的任务数,而 Ri R i 表示该任务簇中是否包含了 Ri(i=1,2,,n) R i ( i = 1 , 2 , ⋯ , n ) ,在这里为0-1值,具体表示如下:

    Ri={0,1,1nni=1fi(Qk,Mk)>0.8others R i = { 0 , 1 n ∑ i = 1 n f i ( Q k ∗ , M k ∗ ) > 0.8 1 , o t h e r s

           最终,确定的打包任务定价模型以及完成概率模型为:

    Pi=l(Ri)KaE(δ)(K11mρik=1mck)2+(K21mρik=1mDik)2+ξ P i = l ( R i ) K a E ( δ ) ( K 1 1 m ρ i ∑ k = 1 m c k ) 2 + ( K 2 1 m ρ i ∑ k = 1 m D i k ) 2 + ξ

    Zi=0,0.042634Pi(Qi+Mi)f(Qi,Mi)(a+b)Di¯¯¯¯¯¯,1,0.042634Pi(Qi+Mi)f(Qi,Mi)(a+b)Di¯¯¯¯¯¯<10others0.042634Pi(Qi+Mi)f(Qi,Mi)(a+b)Di¯¯¯¯¯¯90 Z i = { 0 , 0.042634 P i ( Q i + M i ) f ( Q i , M i ) ( a + b ) D i ¯ < 10 0.042634 P i ( Q i + M i ) f ( Q i , M i ) ( a + b ) D i ¯ , o t h e r s 1 , 0.042634 P i ( Q i + M i ) f ( Q i , M i ) ( a + b ) D i ¯ ≥ 90

    5.3.2 问题总结及分析

           同问题二,我们最终可以求解出打包方案的实际收益总值为 45163 45163 ,未完成的任务数为 174 174 个,项目的理想收益为 51974 51974 。相对问题二中未使用打包方案而言,任务完成率提高了 9.341% 9.341 % ,收益率提高了 13.641% 13.641 %
           通过上述结果显示,我们可以得出结论:制订打包方案在一定程度上不仅能够提高APP平台任务的效率,同时还能够提高自身的效益。

    5.4 问题四

    六、模型的改进

    六、模型评价及推广

    参考文献

    [1]潘斌,于晶贤,衣娜. 数学建模教程[M]. 化学工业出版社,2017.
    [2]韩中庚. 数学建模方法及其应用[M]. 高等教育出版社,2017.

    附录

    附录一:数据处理程序文件

    import pandas as pd
    import numpy as np
    from matplotlib import pyplot as plt
    import os
    import numpy as np
    
    
    d = os.path.dirname(__file__)
    parent_path = os.path.dirname(d)
    data_path1 = parent_path + "/problems/附件一:已结束项目任务数据.xls"
    data_path2 = parent_path + "/problems/附件二:会员信息数据.xls"
    data_path3 = parent_path + "/newdata/after_deal.csv"
    data_path4 = parent_path + "/newdata/data1.csv"
    data_path5 = parent_path + "/newdata/data2.csv"
    data_path6 = parent_path + "/newdata/true_data1.csv"
    data_path7 = parent_path + "/newdata/true_data2.csv"
    
    
    
    def deal_column(data_path, sheet):
        data = pd.ExcelFile(data_path)
        df = data.parse(sheet)
        locations = df["会员位置(GPS)"]
        location_jing = [location.split(" ")[1] for location in locations]
        location_wei = [location.split(" ")[0] for location in locations]
        df["会员gps经度"] = location_jing
        df["会员gps纬度"] = location_wei
        df.to_csv(d + "/after_deal.csv", index=False)
    
    
    def create_city1(data_path, path_name):
        df = pd.ExcelFile(data_path).parse("t_tasklaunch")
        cities = [each["详细地址"][3:6] for index, each in df.iterrows()]
        df["城市"] = cities
        df.to_csv(path_name, index=False)
    
    
    
    def create_city2(data_path, path_name):
        df = pd.read_csv(data_path, encoding="gbk")
        cities = [each["详细地址"][3:6] for index, each in df.iterrows()]
        df["城市"] = cities
        df.to_csv(path_name, index=False)
    
    
    def delete_data1(data_path, error_file, true_file):
        df = pd.read_csv(data_path, encoding="gbk")
        groups = df.groupby("城市")
        error_group = pd.DataFrame(columns=["任务号码","任务gps 纬度","任务gps经度","任务标价","任务执行情况","详细地址","城市"])
        true_group = pd.DataFrame(columns=["任务号码","任务gps 纬度","任务gps经度","任务标价","任务执行情况","详细地址","城市"])
        for city, group in groups:
            if city not in ["佛山市","广州市","深圳市","东莞市"]:
                error_group = pd.concat([error_group, group])
            else:
                true_group = pd.concat([true_group, group])
        error_group.to_csv(error_file, index=False)
        true_group.to_csv(true_file, index=False)
    
    
    def delete_data2(data_path, error_file, true_file):
        df = pd.read_csv(data_path)
        groups = df.groupby("城市")
        error_group = pd.DataFrame(columns=["会员编号","会员位置(GPS)","预订任务限额","预订任务开始时间","信誉值","会员gps经度","会员gps纬度","详细地址","城市"])
        true_group = pd.DataFrame(columns=["会员编号","会员位置(GPS)","预订任务限额","预订任务开始时间","信誉值","会员gps经度","会员gps纬度","详细地址","城市"])
        for city, group in groups:
            if city not in ["佛山市","广州市","深圳市","东莞市"]:
                error_group = pd.concat([error_group, group])
            else:
                true_group = pd.concat([true_group, group])
        error_group.to_csv(error_file, index=False)
        true_group.to_csv(true_file, index=False)
    
    # delete_data1(data_path4, parent_path+"/newdata/error_data1.csv", parent_path+"/newdata/true_data1.csv")
    
    
    
    def append_length(file_path, jing_value2, wei_value2, file_name, encoding):
        df1 = pd.read_csv(file_path, encoding=encoding)
        length = []
        for index1, each_data1 in df1.iterrows():
            jing_value1 = each_data1["任务gps经度"]
            wei_value1 = each_data1["任务gps 纬度"]
            distance = int(6371 * np.arccos(np.sin(wei_value1)*np.sin(wei_value2)+np.cos(wei_value1)*np.cos(wei_value2)*np.cos(jing_value1-jing_value2)))
            length.append(distance)
        df1["与中心距离"] = length
        df1.to_csv(file_name, index=False)
    
    # append_length(parent_path + "/newdata/cleaneddata/data1_gz.csv", 113.27, 23.13, parent_path + "/newdata/cleaneddata/final_data1_gz.csv", "gbk")
    # append_length(parent_path + "/newdata/cleaneddata/data1_fs.csv", 113.12, 23.02, parent_path + "/newdata/cleaneddata/final_data1_fs.csv", "gbk")
    # append_length(parent_path + "/newdata/cleaneddata/data1_dg.csv", 113.75, 23.05, parent_path + "/newdata/cleaneddata/final_data1_dg.csv", "gbk")
    # append_length(parent_path + "/newdata/cleaneddata/data1_sz.csv", 114.05, 22.55, parent_path + "/newdata/cleaneddata/final_data1_sz.csv", "gbk")
    
    
    
    def split_data(file_path, file1, file2, file3,file4, encoding):
        df = pd.read_csv(file_path, encoding=encoding)
        groups = df.groupby("城市")
        for city, group in groups:
            if city == "广州市":
                group.to_csv(file1, index=False)
            if city == "佛山市":
                group.to_csv(file2, index=False)
            if city == "深圳市":
                group.to_csv(file3, index=False)
            if city == "东莞市":
                group.to_csv(file4, index=False)
    
    #split_data(data_path6, parent_path + "/newdata/cleaneddata/data1_gz.csv", parent_path + "/newdata/cleaneddata/data1_fs.csv", parent_path + "/newdata/cleaneddata/data1_sz.csv", parent_path + "/newdata/cleaneddata/data1_dg.csv", "gbk")
    #split_data(data_path7, parent_path + "/newdata/cleaneddata/data2_gz.csv", parent_path + "/newdata/cleaneddata/data2_fs.csv", parent_path + "/newdata/cleaneddata/data2_sz.csv",  parent_path + "/newdata/cleaneddata/data2_dg.csv", "utf-8")
    
    
    def concat_data_tool(file_path1, file_path2):
        df1 = pd.read_csv(file_path1, encoding="gbk")
        df2 = pd.read_csv(file_path2, encoding="utf-8")
        concat_data = []
        for index1, each_data1 in df1.iterrows():
            jing_value1 = each_data1["任务gps经度"]
            wei_value1 = each_data1["任务gps 纬度"]
            d_data = []
            for index2, each_data2 in df2.iterrows():
                jing_value2 = each_data2["会员gps经度"]
                wei_value2 = each_data2["会员gps纬度"]
                distance = int(6371 * np.arccos(np.sin(wei_value1)*np.sin(wei_value2)+np.cos(wei_value1)*np.cos(wei_value2)*np.cos(jing_value1-jing_value2)))
                if distance < 500:
                    d_data.append(index2)
            concat_data.append(d_data)
        return concat_data
    
    def concat_data(data_path1, data_path2, data_list, file_name):
        df1 = pd.read_csv(data_path1, encoding="gbk")
        df2 = pd.read_csv(data_path2, encoding="utf-8")
        datas = []
        for indexs in data_list:
            temp_df = df2.iloc[indexs, :]
            mean_df = np.mean(temp_df)
            mean_df["会员集中度"] = len(indexs)
            datas.append([mean_df["信誉值"], mean_df["预订任务限额"], mean_df["会员集中度"]])
        concat_df = df1.join(pd.DataFrame(datas, columns=["信誉值","预定任务限额","会员集中度"]))
        concat_df.to_csv(file_name, index=False)
    
    #if __name__ == "__main__":
    #   concat_d = concat_data_tool(data_path6, data_path7)
    #    concat_data(data_path6, data_path7, concat_d, parent_path + "/newdata/concat_data.csv")
    
    def split_yes_no(file_name1, file_name2):
        df = pd.read_csv(data_path6, encoding="gbk")
        for status, group in df.groupby("任务执行情况"):
            if status == 0:
                group.to_csv(file_name1, index=False)
            else:
                group.to_csv(file_name2, index=False)
    
    split_yes_no(parent_path+"/newdata/no.csv", parent_path+"/newdata/yes.csv")
    
    
    
    """
        data = []
        for index2, each_data2 in df2.iterrows():
            jing_value2 = each_data2["会员gps经度"]
            wei_value2 = each_data2["会员gps纬度"]
            R = [[],[]]
            for index1, each_data1 in df1.iterrows():
                jing_value1 = each_data1["任务gps经度"]
                wei_value1 = each_data1["任务gps 纬度"]
                distance = int(6371 * np.arccos(np.sin(wei_value1)*np.sin(wei_value2)+np.cos(wei_value1)*np.cos(wei_value2)*np.cos(jing_value1-jing_value2)))
                R[0].append(each_data1["任务号码"])
                R[1].append(distance)
            print(index2)
            a = R[0]
            b = R[1]
            data.append([index2, a[b.index(np.min(b))], np.min(R[1]), df2.iloc[index2]["预订任务限额"], int(df2.iloc[index2]["预订任务开始时间"].split(":")[0])*3600 + int(df2.iloc[index2]["预订任务开始时间"].split(":")[1])*60 + int(df2.iloc[index2]["预订任务开始时间"].split(":")[2])])        
        print("*"*100)
        print(np.array(data))
        print(len(data))
        calc_data = pd.DataFrame(data, columns=["会员编号", "任务编号", "两者距离", "预定任务限额", "预定任务时间"])
        mean_data = []
        for index, group in calc_data.groupby("任务编号"):
            print([index] + list(np.mean(group.iloc[:,1:])))
            mean_data.append([index] + list(np.mean(group.iloc[:,1:])))
        mean_df = pd.DataFrame(mean_data, columns=["任务编号", "两者距离", "预定任务限额", "预定任务时间"])
        sort_mean_df = mean_df.sort_values(by="任务编号", ascending=True)
        real_data = df1.join(sort_mean_df)
        real_data.to_csv(data_file)
    """
    # concat_data(parent_path + "/newdata/cleaneddata/data1_gz.csv", parent_path + "/newdata/cleaneddata/data2_gz.csv", parent_path + "/newdata/cleaneddata/data_gz.csv")

    附录二:数据可视化程序文件

    import pandas as pd
    from matplotlib import pyplot as plt
    from matplotlib.font_manager import FontProperties
    import os
    import numpy as np
    import matplotlib as mpl
    
    mpl.rcParams['font.sans-serif'] = ['SimHei']
    mpl.rcParams['axes.unicode_minus'] = False
    
    font = FontProperties(fname=r"C:\windows\fonts\simsun.ttc", size=10)
    d = os.path.dirname(__file__)
    parent_path = os.path.dirname(d)
    
    def draw_scatter(file_path, color, marker, city, image_path):
        df = pd.read_csv(file_path)
        p = df["任务标价"]
        d = df["与中心距离"]
        plt.scatter(d/100, p, s=10, c=color, alpha=0.6, marker=marker)
        plt.title("{}任务位置与定价的关系".format(city), fontproperties=font)
        plt.xlabel("Distance/x100km")
        plt.ylabel("Price")
        plt.savefig(image_path)
        plt.show()
    
    # draw_scatter(parent_path + "/newdata/cleaneddata/final_data1_gz.csv", "red", "o", "广州市", parent_path + "/images/scatter_gz.jpg")
    # draw_scatter(parent_path + "/newdata/cleaneddata/final_data1_sz.csv", "red", "o", "深圳市", parent_path + "/images/scatter_sz.jpg")
    # draw_scatter(parent_path + "/newdata/cleaneddata/final_data1_fs.csv", "red", "o", "佛山市", parent_path + "/images/scatter_fs.jpg")
    # draw_scatter(parent_path + "/newdata/cleaneddata/final_data1_dg.csv", "red", "o", "东莞市", parent_path + "/images/scatter_dg.jpg")
    
    def get_mean_price(file_path):
        df = pd.read_csv(file_path)
        p = df["任务标价"]
        mean_price = np.mean(p)
        return mean_price
    
    def draw_price_(file_path, column, color, marker, title, xlabel, image_path):
        df = pd.read_csv(file_path)
        p = df["任务标价"]
        d = df[column]
        plt.scatter(d/100, p, s=10, c=color, alpha=0.6, marker=marker)
        plt.title("{}与定价的关系".format(title), fontproperties=font)
        plt.xlabel(xlabel)
        plt.ylabel("Price")
        plt.savefig(image_path)
        plt.show()  
    
    # draw_price_(parent_path + "/newdata/concat_data.csv", "信誉值", "red", "*", "信誉值", "Credibility", parent_path + "/images/credit_price.jpg")
    # draw_price_(parent_path + "/newdata/concat_data.csv", "预定任务限额", "red", "*", "预定任务限额", "Num", parent_path + "/images/num_price.jpg")
    # draw_price_(parent_path + "/newdata/concat_data.csv", "会员集中度", "red", "*", "会员集中度", "Density", parent_path + "/images/density_price.jpg")
    
    def draw_no_scatter():
        df = pd.read_csv(parent_path + "/newdata/no.csv")
        plt.scatter(np.arange(313), df["任务标价"], s=20, c="red", alpha=0.6, marker="*")
        plt.title("任务未完成数据的价格分布")
        plt.xlabel("Mission")
        plt.ylabel("Price")
        plt.savefig(parent_path + "/images/no_price.jpg")
        plt.show()
    
    # draw_no_price()
    
    def draw_no_bar():
        df = pd.read_csv(parent_path + "/newdata/no.csv")
        df1 = df[(65 <= df["任务标价"]) & (df["任务标价"] < 70)]
        df2 = df[(70 <= df["任务标价"]) & (df["任务标价"] < 75)]
        df3 = df[(75 <= df["任务标价"]) & (df["任务标价"] < 80)]
        df4 = df[(80 <= df["任务标价"]) & (df["任务标价"] < 85)]
        data_len = [len(df1), len(df2), len(df3), len(df4)]
        plt.barh(np.arange(4), data_len, height=0.6, alpha=0.7, color="yellowgreen")
        plt.ylabel("Price Region")
        plt.xlabel("Num")
        plt.title("未完成价格条形图")
        plt.yticks(np.arange(4), ["65-69", "70-74", "75-79", "80-85"], rotation=45, size=13)
        for x, value in enumerate(data_len):
            plt.text(y=x, x=value, s="{}".format(value), ha="center")
        plt.savefig(parent_path+"/images/price_bar.jpg")
        plt.show()
    
    # draw_no_bar()
    
    def draw_no_pie():
        df = pd.read_csv(parent_path + "/newdata/no.csv")
        df1 = df[(65 <= df["任务标价"]) & (df["任务标价"] < 70)]
        df2 = df[(70 <= df["任务标价"]) & (df["任务标价"] < 75)]
        df3 = df[(75 <= df["任务标价"]) & (df["任务标价"] < 80)]
        df4 = df[(80 <= df["任务标价"]) & (df["任务标价"] < 85)]
        data_len = [len(df1), len(df2), len(df3), len(df4)]
        plt.pie(x=data_len, labels=["65-69", "70-74", "75-79", "80-85"], autopct="%.0f%%", shadow=True, radius=1.2)
        plt.legend(["65-69", "70-74", "75-79", "80-85"], loc=&