数据分析,数据挖掘基本算法_数据的基本分析

数据分析,数据挖掘基本算法

在本系列教程的第1部分中,您学习了如何将单个表从Informix®移动到Spark,如何将整个数据库放入Spark,以及如何为Informix构建特定的方言。

第二部分的重点是分析,并从数据中获得基本见识。 绝对不需要Informix的知识。

企业就绪

您正在使用模仿企业数据库的Informix商店演示数据库。 该公司是一家运动器材批发商,主要销售给妈妈和流行商店。 本教程仅使用一个表:orders表。 订单表在Apache Spark中导入后的架构如下所示。

订单表架构

关于数据库图的小注释:在原始数据库中,有主键,外键,约束,本机数据类型(例如SERIAL )。 所有这些都转换为Spark的数据类型和简化的结构。 不需要索引,约束或键。

出货时间

您的第一个练习是衡量从客户下订单到发货之间仓库需要多少时间。

当然,使用Spark进行此操作有点像使用核电站为您的手机加油,但是您会在Spark分析世界中逐步发现!

您可以从GitHub下载代码。

摘要并遍历代码

做好准备 第一次导入似乎有点不寻常,因为Spark有很多预定义的功能。 如有必要,org.apache.spark.sql.functions包中的函数列表是有用的参考。

在以下代码中,将datediff替换为*以导入所有功能。 但是,对于本教程,仅需要datediff 。 您可能已经知道它的作用。

import static org.apache.spark.sql.functions.datediff;

其余的导入类与第1部分中使用的类相似。 在您遍历代码时,我喜欢共享导入。 如果我不这样做,使用同名来引用类可能会非常混乱。

import java.sql.Connection;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.spark.sql.Dataset;
import org.apache.spark.sql.Row;
import org.apache.spark.sql.SparkSession;
import org.apache.spark.sql.jdbc.JdbcDialect;
import org.apache.spark.sql.jdbc.JdbcDialects;

import net.jgp.labs.informix2spark.utils.Config;
import net.jgp.labs.informix2spark.utils.ConfigManager;
import net.jgp.labs.informix2spark.utils.InformixJdbcDialect;
import net.jgp.labs.informix2spark.utils.K;

启动应用程序的时间:

public class TimeToShipApp {

  public static void main(String[] args) {
    TimeToShipApp app = new TimeToShipApp();
    app.start();
  }

  private void start() {

使用Spark的本地模式启动会话:

SparkSession spark = SparkSession
        .builder()
        .appName("Time to Ship")
        .master("local")
        .getOrCreate();

即使该示例不需要它,注册Informix方言也是一个好习惯:

JdbcDialect dialect = new InformixJdbcDialect();
    JdbcDialects.registerDialect(dialect);

您将获得Informix参数:

Config config = ConfigManager.getConfig(K.INFORMIX);

创建要使用的所有表的列表(并将其添加到数据湖)。 在此示例中,这似乎有些过头,因为我们仅使用一个表,但在其他示例中重复使用了相同的思想(重复可以帮助您学习)。

List<String> tables = new ArrayList<>();
    tables.add("orders");

如您所知,映射包含按键索引的值。 每个来自Spark的数据框都存储在一个映射中,其键是表的名称,值是包含数据的数据框。

Map<String, Dataset<Row>> datalake = new HashMap<>();
    for (String table : tables) {
      System.out.print("Loading table [" + table
          + "] ... ");
      Dataset<Row> df = spark.read()
          .format("jdbc")
          .option("url", config.getJdbcUrl())
          .option("dbtable", table)
          .option("user", config.getUser())
          .option("password", config.getPassword())
          .option("driver", config.getDriver())
          .load();

      datalake.put(table, df);
      System.out.println("done.");
    }

至此,此执行的结果是:

Loading table [orders] ... done.
We have loaded 1 table(s) in our data lake.

现在您可以利用数据了。 使用ordersDF数据ordersDF

Dataset<Row> ordersDf = datalake.get("orders");

使用withColumn()方法创建一个新列。 这一新列是datediff()Spark SQL函数的结果 。 该函数有两个参数:结束日期和开始日期。

ordersDf = ordersDf.withColumn(
        "time_to_ship", 
        datediff(ordersDf.col("ship_date"), ordersDf.col("order_date")));

注意:

datediff(ordersDf.col("ship_date"), ordersDf.col("order_date"))

与以下内容不同:

datediff(ordersDf.col("order_date"), ordersDf.col("ship_date"))

您真正要做的是减法。 因此,将最大的数字(或更近的日期)放在第一位; 否则,您将拥有一个负数。

此时,如果您打印数据框的模式,您将看到:

ordersDf.printSchema();
root
 |-- order_num: integer (nullable = false)
 |-- order_date: date (nullable = true)
 |-- customer_num: integer (nullable = false)
 |-- ship_instruct: string (nullable = true)
 |-- backlog: string (nullable = true)
 |-- po_num: string (nullable = true)
 |-- ship_date: date (nullable = true)
 |-- ship_weight: decimal(8,2) (nullable = true)
 |-- ship_charge: decimal(6,2) (nullable = true)
 |-- paid_date: date (nullable = true)
 |-- time_to_ship: integer (nullable = true)

看到您添加的列? 它称为time_to_ship ,其类型是整数(并且可以为null )。

如果您查看数据:

ordersDf.show(10);
    System.out.println("We have " + ordersDf.count() + " orders");
+---------+----------+------------+--------------------+-------+----------+----------+-----------+-----------+----------+------------+
|order_num|order_date|customer_num|       ship_instruct|backlog|    po_num| ship_date|ship_weight|ship_charge| paid_date|time_to_ship|
+---------+----------+------------+--------------------+-------+----------+----------+-----------+-----------+----------+------------+
|     1001|2008-05-20|         104|express          ...|      n|B77836    |2008-06-01|      20.40|      10.00|2008-07-22|          12|
|     1002|2008-05-21|         101|PO on box; delive...|      n|9270      |2008-05-26|      50.60|      15.30|2008-06-03|           5|
|     1003|2008-05-22|         104|express          ...|      n|B77890    |2008-05-23|      35.60|      10.80|2008-06-14|           1|
|     1004|2008-05-22|         106|ring bell twice  ...|      y|8006      |2008-05-30|      95.80|      19.20|      null|           8|
|     1005|2008-05-24|         116|call before deliv...|      n|2865      |2008-06-09|      80.80|      16.20|2008-06-21|          16|
|     1006|2008-05-30|         112|after 10 am      ...|      y|Q13557    |      null|      70.80|      14.20|      null|        null|
|     1007|2008-05-31|         117|                null|      n|278693    |2008-06-05|     125.90|      25.20|      null|           5|
|     1008|2008-06-07|         110|closed Monday    ...|      y|LZ230     |2008-07-06|      45.60|      13.80|2008-07-21|          29|
|     1009|2008-06-14|         111|next door to groc...|      n|4745      |2008-06-21|      20.40|      10.00|2008-08-21|           7|
|     1010|2008-06-17|         115|deliver 776 King ...|      n|429Q      |2008-06-29|      40.60|      12.30|2008-08-22|          12|
+---------+----------+------------+--------------------+-------+----------+----------+-----------+-----------+----------+------------+
only showing top 10 rows
We have 23 orders

您可以在time_to_ship列中看到订单#1006具有空值,因为它尚未发货。 当分析发货时间时,您会发现它不是Amazon Prime!

接下来,您将希望摆脱n​​ull值,但是数据帧是不可变的,这意味着数据无法更改。 要解决此问题,请创建一个新的数据框并排除您不喜欢的值。 是的,数据框不是SQL表,没有DELETE FROM

Dataset<Row> ordersDf2 = ordersDf.filter(
        "time_to_ship IS NOT NULL");
    ordersDf2.printSchema();
    ordersDf2.show(5);
    System.out.println("We have " + ordersDf2.count()
        + " delivered orders");

  }
}

输出为:

+---------+----------+------------+--------------------+-------+----------+----------+-----------+-----------+----------+------------+
|order_num|order_date|customer_num|       ship_instruct|backlog|    po_num| ship_date|ship_weight|ship_charge| paid_date|time_to_ship|
+---------+----------+------------+--------------------+-------+----------+----------+-----------+-----------+----------+------------+
|     1001|2008-05-20|         104|express          ...|      n|B77836    |2008-06-01|      20.40|      10.00|2008-07-22|          12|
|     1002|2008-05-21|         101|PO on box; delive...|      n|9270      |2008-05-26|      50.60|      15.30|2008-06-03|           5|
|     1003|2008-05-22|         104|express          ...|      n|B77890    |2008-05-23|      35.60|      10.80|2008-06-14|           1|
|     1004|2008-05-22|         106|ring bell twice  ...|      y|8006      |2008-05-30|      95.80|      19.20|      null|           8|
|     1005|2008-05-24|         116|call before deliv...|      n|2865      |2008-06-09|      80.80|      16.20|2008-06-21|          16|
+---------+----------+------------+--------------------+-------+----------+----------+-----------+-----------+----------+------------+
only showing top 5 rows
We have 22 delivered orders

但是等等,到底发生了什么?

Spark基于惰性评估的概念。 我认为这是当您要孩子做某事时:打扫房间,将衣服放在篮子里,将书放在书架上……通常,这些变化不会发生,除非您说出“ now”(有时声音会稍大一些)。 这是他们等待上手的动作信号。 Spark完全相同。

这里的负责人称为催化剂。 Catalyst是一种优化器,可找到执行转换的最佳方法。 再说一次,想想这个小孩子,他需要从架子上脱下衣服才能放回书本。 在2.2版中,Spark向Catalyst添加了基于成本的优化器,这是IBM的重要贡献。

什么是数据框?

对于Apache Spark,数据框几乎就像关系数据库世界中的表一样。 好吧,差不多...

  • 数据是不可变的,这意味着它不会改变。 使用SQL,您可以轻松地UPDATE数据并在表中INSERT新行。 数据框是不同的。 要执行这些操作,您每次必须创建一个新的数据框。 这是您经常要做的事情。
  • 像表一样,数据框具有元数据:列具有名称,类型以及它们是否需要值( nullablenullable属性)。 与表不同,您不会找到索引,外键,复合键或触发器。
  • 由于Spark具有分析性,因此添加列和执行转换很容易,而使用RDBMS表则很棘手。

数据框API是开发人员使用的API。 您将比Facebook访问Class Dataset页面更多! 直接从此API,您可以访问列信息,执行联接和联合等等。 (本系列文章的第3部分将探讨此API。)

在Java中,数据帧被实现为Dataset<Row> 。 存储依赖于群集中的分区。 Spark提供了较低级别的API,因此您可以重新分区并了解执行计划,但这不在本文的讨论范围之内。 从Spark 2开始,存储由称为Tungsten的组件处理,该组件比Java / Scala对象更有效。

图2显示了Spark数据帧的API,实现和存储。

API,实施和Spark数据帧的存储。

你学到了什么

希望您现在对Spark如何存储数据以及如何通过dataframe API更好地了解。 您还了解了内置函数以及在哪里可以找到它们。 最重要的是,您现在具有构建更复杂的分析和机器学习的基础……这就是本系列教程的下一步。

走得更远


翻译自: https://www.ibm.com/developerworks/opensource/library/ba-offloading-informix-data-spark-2/index.html

数据分析,数据挖掘基本算法

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值