共享单车之数据存储


第1关:获取工作簿中的数据

相关知识
获取工作簿中的信息,我们可以使用Java POI(POI是一个提供API给Java程序对Microsoft Office格式档案读和写的功能)提供的Workbook类来操作。

为了完成本关任务,你需要掌握:如何获取Wookbook的数据。

读取一个Wookbook中数据
读取工作簿中的内容大致分为下列几个步骤:

使用WorkbookFactory新建一个工作簿(Wookbook)
InputStream resourceAsStream = SaveData.class.getClassLoader().getResourceAsStream(“data.xls”);//通过类加载器获取本地文件
Workbook workbook = WorkbookFactory.create(resourceAsStream);
获取给定索引处的Sheet对象。
Sheet sheet = workbook.getSheetAt(0);//拿到Wookbook中的第一个Sheet
说明:一个Wookbook中可能存在多个Sheet,因此需要指定索引,如下图:

通过Sheet对象获取指定行和行内单元格。
Row row = sheet.getRow(1);//首行一般为说明,因此我们直接从第一行进行获取
Cell cell = row.getCell(0);//获取当前行第一个单元格
获取单元格中的值。

上图观察表结构数据trip_id为数字类型,时间为字符类型,在获取数据时我们必须遵循类型规则,对应获取。

//1.获取第一行中trip_id列的第一个值(33404951)
double numericCellValue = row.getCell(0).getNumericCellValue();
DecimalFormat formatter = new DecimalFormat(“########”);//一个#表示一个数字
String trip_id =formatter.format(numericCellValue);//我们需要使用DecimalFormat将数据格式化
//2.获取第一行中开始时间单元格的值
FastDateFormat instance = FastDateFormat.getInstance(“MM/dd/yyyy HH:mm”);
String beginTimeValue = row.getCell(1).getStringCellValue();
//为了方便后面的数据分析计算我们将需要将时间格式转为时间戳
long begintime = instance.parse(beginTimeValue).getTime();
//3.获取第一行开始经度单元格的值
double start_longitude = row.getCell(7).getNumericCellValue();
DecimalFormat formatter = new DecimalFormat(“###.######”);//#表示一个数字,不包括0
String longitude = formatter.format(start_longitude);
获取当前sheet中的物理定义行数
//为了完整的将整个Sheet中的数据全部存储,我们需要知道整个Sheet中有多少条数据,然后对其遍历
int rows = sheet.getPhysicalNumberOfRows();
编程要求
在右侧编辑器Begin-End中补充代码,获取data.xls文件中的数据,具体获取以下数据并将结果打印:trip_id、开始时间、结束经度、车辆id。

文件数据格式如下:

trip_id 开始时间 结束时间 车辆id 出发地 目的地 所在城市 开始经度 开始纬度 结束经度 结束纬度
33404951 7/1/2017 0:09 7/1/2017 0:45 5996 韩庄村北782米 韩庄村北782米 河北省保定市雄县 39.043732 116.260139 39.043732 116.260139
33463211 7/1/2017 1:01 7/1/2017 11:13 6342 韩庄村北782米 39.043732 116.260139 NA NA
33415440 7/1/2017 1:59 7/1/2017 2:12 6273 擎天矿用材料有限公司北609米 河北省保定市雄县G45(大广高速) 河北省保定市雄县G45(大广高速) 39.041691 116.235352 39.044701 116.252441
注意:表中有非法数据,我们在获取时为了避免出错或者获取到空的数据,可以使用try-catch将其抛出。

测试说明
平台会对你编写的代码进行测试:

测试输入:无;
预期输出:
骑行id:33404951,开始时间:1498838940000,车辆id:5996,结束经度:39.043732
骑行id:33415440,开始时间:1498845540000,车辆id:6273,结束经度:39.044701

开始你的任务吧,祝你成功!
示例代码如下:

package com.educoder.savedata;
import java.io.InputStream;
import java.text.DecimalFormat;
import org.apache.commons.lang3.time.FastDateFormat;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
public class SaveWookbook {
    public static void main(String[] args) throws Exception {
        /******** **    Begin    ****** ****/
        //1.通过类加载器获取本地文件并新建一个工作簿
        InputStream resourceAsStream = SaveWookbook.class.getClassLoader().getResourceAsStream("data.xls");
        Workbook workbook = WorkbookFactory.create(resourceAsStream);
        //2.拿到工作簿中第一个Sheet
        Sheet sheet = workbook.getSheetAt(0);
        //3.获取当前Sheet中的行数
        int rows = sheet.getPhysicalNumberOfRows();
        //4.对所有有效数据进行遍历并输出(期间无效数据通过异常捕获方式清除)
        for (int n = 1; n < rows; n++) {
            Row row = sheet.getRow(n);
            //通过异常方式清除格式不准确、数据不存在的无效行
            try {
                //trip_id
                DecimalFormat formatter1 = new DecimalFormat("########");
                String trip_id = formatter1.format(row.getCell(0).getNumericCellValue());
                //开始时间
                FastDateFormat instance = FastDateFormat.getInstance("MM/dd/yyyy HH:mm");
                String beginTimeValue = row.getCell(1).getStringCellValue();
                long begintime = instance.parse(beginTimeValue).getTime();
                //车辆id
                int car_id = (int)row.getCell(3).getNumericCellValue();
                //结束经度
                double start_longitude = row.getCell(9).getNumericCellValue();
                DecimalFormat formatter2 = new DecimalFormat("###.######");//#表示一个数字,不包括0
                String longitude = formatter2.format(start_longitude);
                System.out.println("骑行id:"+trip_id+",开始时间:"+begintime+",车辆id:"+car_id+",结束经度:"+longitude);
            } catch (Exception e) {
            }
        }
        /******** **    End    ******* ***/
    }
}

在这里插入图片描述

第2关:保存共享单车数据

相关知识
为了完成本关任务,你需要掌握:

如何创建HBase表;
如何读取文件;
了解共享单车数据表格式以及如何获取数据;
如何存储到HBase。
如何创建HBase表
com.util.HBaseUtil类封装了对应的创建Hbase表方法createTable

示例如下:

HBaseUtil.createTable(“t_shared_bicycle”, “info”);//创建拥有一个列族的info的表t_shared_bicycle,一个列族可拥有任意数量的列。
获取本地文件
文件存放目录为src/main/resources,我们可以通过类加载器加载共享单车数据文件dataResources.xls:

InputStream resourceAsStream = SaveData.class.getClassLoader().getResourceAsStream(“dataResources.xls”);
共享单车数据结构和获取
dataResources.xls文件格式如下:

trip_id 开始时间 结束时间 车辆id 出发地 目的地 所在城市 开始经度 开始纬度 结束经度 结束纬度
33404951 7/1/2017 0:09 7/1/2017 0:45 5996 韩庄村北782米 韩庄村北782米 河北省保定市雄县 39.043732 116.260139 39.043732 116.260139
33404950 7/1/2017 0:11 7/1/2017 0:45 5777 河北省保定市雄县G45(大广高速) 乡里乡情铁锅炖东499米 河北省保定市雄县 39.044159 116.251579 39.04652 116.237411
33404947 7/1/2017 1:59 7/1/2017 2:12 6342 韩庄村北782米 韩庄村北782米 河北省保定市雄县 39.043732 116.260139 39.043732 116.260139
如何存储到HBase
com.util.HBaseUtil类封装了对应的批量存储到Hbase表方法putByTable。示例如下:

List puts = new ArrayList<>();// 一个PUT代表一行数据,每个Put有唯一的ROWKEY
Put put = new Put(Bytes.toBytes(“33404951”)); //创建ROWKEY为33404951的PUT
byte[] family = Bytes.toBytes(“info”);
put.addColumn(family,Bytes.toBytes(“bicycleId”), Bytes.toBytes(String.valueOf(5996)));//在列族info中,增加字段名称为bicycleId,值为5996的元素
put.addColumn(family,Bytes.toBytes(“departure”), Bytes.toBytes(“韩庄村北782米”));//在列族info中,增加字段名称为departure,值为韩庄村北782米的元素
puts.add(put);
HBaseUtil.putByTable(“t_shared_bicycle”,puts);//批量保存数据到t_shared_bicycle
编程要求
根据提示,在右侧编辑器Begin-End中补充savaBicycleData方法,完成如下操作:

创建拥有列族info的表t_shared_bicycle;
将唯一骑行trip_id设为表的ROWKEY;
将出发地 = 目的地或者目的地 = 所在城市的无效数据清除;
把文件dataResources.xls中相应的数据存到Hbase表t_shared_bicycle中。
t_shared_bicycle表结构如下

列族名称 字段 对应的文件的描述 ROWKEY (格式为:骑行id)
info beginTime 开始时间 trip_id
info endTime 结束时间 trip_id
info bicycleId 车辆id trip_id
info departure 出发地 trip_id
info destination 目的地 trip_id
info city 所在城市 trip_id
info start_longitude 开始经度 trip_id
info stop_longitude 结束经度 trip_id
info start_latitude 开始纬度 trip_id
info stop_latitude 结束纬度 trip_id
提示:注意使用try-catch将无效数据或非法数据进行抛出。

测试说明
平台会对你编写的代码进行测试,数据量较大,评测时间可能较长,请耐心等待:

测试输入:37785165
预期输出:
rowCount–>331850
info:beginTime 1501500120000
info:bicycleId 6280
info:city 河北省保定市雄县
info:departure 东方红家园西南121米
info:destination 沙辛庄村南940米
info:endTime 1501500840000
info:start_latitude 116.13826
info:start_longitude 39.144981
info:stop_latitude 116.13237
info:stop_longitude 39.13525

说明:由于数据过多,我们将输出ROWKEY为37785165的信息。

开始你的任务吧,祝你成功!
示例代码如下:

package com.educoder.savedata;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.commons.lang3.time.FastDateFormat;
import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import com.educoder.util.HBaseUtil;
/* 
* 读取共享单车城市行车数据
* 
*/
public class SaveData {
    public static void SaveBicycleData()  throws Exception {
        /******** **   Begin   ******* ***/
       HBaseUtil.createTable("t_shared_bicycle", "info");
        InputStream resourceAsStream = SaveData.class.getClassLoader().getResourceAsStream("dataResources.xls");
        Workbook workbook = WorkbookFactory.create(resourceAsStream);
        Sheet sheet = workbook.getSheetAt(0);
        int rows = sheet.getPhysicalNumberOfRows();
        List<Put> puts = new ArrayList<Put>();
        for (int n = 1; n < rows; n++) {
            // 通过异常方式清除格式不准确、数据不存在的无效行
            try {
                Row row = sheet.getRow(n);
                // 唯一骑行id,当作行rowkey
                DecimalFormat formatter1 = new DecimalFormat("########");
                String trip_id = formatter1.format(row.getCell(0).getNumericCellValue());
                Put put = new Put(Bytes.toBytes(trip_id));
                byte[] family = Bytes.toBytes("info");
                // 开始时间
                FastDateFormat instance = FastDateFormat.getInstance("MM/dd/yyyy HH:mm");
                String beginTimeValue = row.getCell(1).getStringCellValue();
                Date parse = instance.parse(beginTimeValue);
                put.addColumn(family, Bytes.toBytes("beginTime"), Bytes.toBytes(String.valueOf(parse.getTime())));
                // 结束时间
                String endTimeValue = row.getCell(2).getStringCellValue();
                Date parse2 = instance.parse(endTimeValue);
                put.addColumn(family, Bytes.toBytes("endTime"), Bytes.toBytes(String.valueOf(parse2.getTime())));
                // 单车识别码
                int bicycleId = (int)row.getCell(3).getNumericCellValue();
                put.addColumn(family, Bytes.toBytes("bicycleId"), Bytes.toBytes(String.valueOf(bicycleId)));
                // 出发地
                String departure = row.getCell(4).getStringCellValue();
                put.addColumn(family, Bytes.toBytes("departure"), Bytes.toBytes(departure));
                // 目的地
                String destination = row.getCell(5).getStringCellValue();
                put.addColumn(family, Bytes.toBytes("destination"), Bytes.toBytes(destination));
                // 所在城市
                String city = row.getCell(6).getStringCellValue();
                put.addColumn(family, Bytes.toBytes("city"), Bytes.toBytes(city));
                // 清除目的地 = 所在城市 或者 出发地 = 目的地 的无效数据
                if (destination.equals(city)|| departure.equals(destination) ) {
                    continue;
                }
                //开始经度
                DecimalFormat formatter2 = new DecimalFormat("###.######");
                String start_longitude = formatter2.format(row.getCell(7).getNumericCellValue());
                put.addColumn(family, Bytes.toBytes("start_longitude"), Bytes.toBytes(String.valueOf(start_longitude)));
                //开始纬度
                String start_latitude = formatter2.format(row.getCell(8).getNumericCellValue());
                put.addColumn(family, Bytes.toBytes("start_latitude"), Bytes.toBytes(String.valueOf(start_latitude)));
                //结束经度
                String stop_longitude = formatter2.format(row.getCell(9).getNumericCellValue());
                put.addColumn(family, Bytes.toBytes("stop_longitude"), Bytes.toBytes(String.valueOf(stop_longitude)));
                //结束纬度
                String stop_latitude = formatter2.format(row.getCell(10).getNumericCellValue());
                put.addColumn(family, Bytes.toBytes("stop_latitude"), Bytes.toBytes(String.valueOf(stop_latitude)));
                puts.add(put);
            } catch (Exception e) {
            }
        }
        HBaseUtil.putByTable("t_shared_bicycle", puts);
        /****** ****   End   ****** ****/
    }
}

在这里插入图片描述


  • 32
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
共享单车使用数据的采集方法主要分为两种:一种是硬件采集,另一种是软件采集。 硬件采集:共享单车通常配备了GPS和GPRS等传感器,这些传感器可以实时记录车辆的位置、速度、行驶距离等信息,然后将这些数据上传到服务器进行存储和分析。此外,一些共享单车还配备了摄像头和传感器等设备,用于采集更多的数据。 软件采集:共享单车的手机App可以采集用户的行为数据,例如用户的行程、时间、里程数、消费金额等信息。这些数据可以通过API接口等方式上传到服务器进行存储和分析。 数据分析方法:对共享单车使用数据进行分析可以有多种方法,下面列举几种常用的方法: 1. 聚类分析:根据用户的行为数据,将用户进行分类,例如短途用户、长途用户、夜间用户等,从而更好地了解用户的需求和习惯。 2. 热力图分析:通过对车辆的位置数据进行热力图分析,可以了解车辆的使用频率、热门地区等信息,从而优化车辆的调度和分布。 3. 时间序列分析:对用户的使用数据进行时间序列分析,例如季节性变化、周末和工作日的差异等,可以更好地了解用户的行为规律和需求。 4. 关联分析:通过对用户的行为数据进行关联分析,例如使用时间和消费金额之间的关系,可以了解用户的消费行为和偏好,从而更好地推广和促销产品。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值