加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 黄冈站长网 (http://www.0713zz.com/)- 数据应用、建站、人体识别、智能机器人、语音技术!
当前位置: 首页 > 大数据 > 正文

使用Java和Python进行数据统计和剖析

发布时间:2022-06-28 23:31:24 所属栏目:大数据 来源:互联网
导读:Java 和 Python 是当今最流行的两种计算机语言。两者都非常成熟,并提供了工具和技术生态系统,帮助我们解决数据科学领域出现的挑战性问题。每种语言都各有优势,我们要知道什么时候应该使用哪种工具,或者什么时候它们应该协同工作相互补充。 Python 是一
  Java 和 Python 是当今最流行的两种计算机语言。两者都非常成熟,并提供了工具和技术生态系统,帮助我们解决数据科学领域出现的挑战性问题。每种语言都各有优势,我们要知道什么时候应该使用哪种工具,或者什么时候它们应该协同工作相互补充。
 
  Python 是一种动态类型语言,使用起来非常简单,如果我们不想接触复杂的程序,它肯定是进行复杂计算的首选语言。Python 提供了优秀的库(Pandas、NumPy、Matplotlib、ScyPy、PyTorch、TensorFlow 等)来支持对数据结构或数组的逻辑、数学和科学操作。
 
  Java 是一种非常健壮的语言,具有强类型,因此有更严格的语法规则,所以不易出现程序错误。与Python一样,它也提供了大量的库来处理数据结构、线性代数、机器学习和数据处理(ND4J、Mahout、Spark、Deeplearning4J 等)。
 
  本文将介绍如何对大量表格数据进行简单的数据分析,并使用 Java 和 Python 计算一些统计数据。我们可以看到使用各个平台进行数据分析的不同技术,对比它们的扩展方式,以及应用并行计算来提高其性能的可行性。
 
  首先定义一个封装数据元素的 Java 记录:
 
  复制
  record InputEntry(String city, String state, double basePrice, double actualPrice) {}
  1.
  记录(record)是 JDK 14 中引入的一种新型类型声明。它是定义提供构造函数、访问器、equals 和哈希实现的不可变类的一种简捷方式。
 
  接下来,读取 CVS 文件并将它们增加到一个列表中:
 
  复制
  List<InputEntry> inputEntries = readRecordEntriesFromCSVFile(recordEntries.csv);
  1.
  为了按城市和州对输入的元素进行分组,将其定义:
 
  复制
  record CityState(String city, String state) {};
  1.
  使用以下类来封装属于一个组的所有元素的统计信息:
 
  复制
  record StatsAggregation(StatsAccumulator basePrice, StatsAccumulator actualPrice) {}
  1.
  StatsAccumulator是Guava 库的一部分。可以将双精度值集合添加到类中,它会计算基本统计数据,例如计数、平均值、方差或标准差。可以使用StatsAccumulator来获取InputEntry的basePrice和actualPrice的统计数据。
 
  现在我们已经拥有了解决问题的所有材料。Java Streams提供了一个强大的框架来实现数据操作和分析。它的声明式编程风格,对选择、过滤、分组和聚合的支持,简化了数据操作和统计分析。它的框架还提供了一个强大的实现,可以处理大量的(甚至是无限的流),并通过使用并行性、懒惰性和短路操作来高效处理。所有这些特性使Java Streams成为解决这类问题的绝佳选择。实现非常简单:
 
  复制
  Map<CityState, StatsAggregation> stats = inputEntries.stream().
      filter(i -> !(i.state().equals("MN") || i.state().equals("CA"))).collect(
          groupingBy(entry -> new CityState(entry.city(), entry.state()),
                     collectingAndThen(Collectors.toList(),
                                       list -> {StatsAccumulator sac = new StatsAccumulator();
                                                  sac.addAll(list.stream().mapToDouble(InputEntry::basePrice));
                                                StatsAccumulator sas = new StatsAccumulator();
                                                  sas.addAll(list.stream().mapToDouble(InputEntry::actualPrice));
                                                 return new StatsAggregation(sac, sas);}
                                         )));
 
  在代码的第 2 行,我们使用Stream::filter. 这是一个布尔值函数,用于过滤列表中的元素。可以实现一个 lambda 表达式来删除任何包含“MN”或“CA”状态的元素。
 
  然后继续收集列表的元素并调用Collectors::groupingBy()(第 3 行),它接受两个参数:
 
  一个分类功能,使用CityState记录来做城市和州的分组(第3行)。
  下游的收集器,包含属于同一<城州>的元素。使用Collectors::collectingAndThen(第 4 行),它采用两个参数分两步进行归约:
  ·我们使用Collectors::toList(第 4 行),它返回一个收集器,它将属于同一<城州>的所有元素放到一个列表中。
 
  ·随后对这个列表进行了整理转换。使用一个lambda函数(第5行至第9行)来定义两个StatsAccumulator(s),在这里分别计算前一个列表中的basePrice和actualPrice元素的统计数据。最后,返回到新创建的包含这些元素的StatsAggregation记录。
 
  正如前文所述,使用Java Streams的优势之一是,它提供了一种简单的机制,可以使用多线程进行并行处理。这允许利用CPU的多核资源,同时执行多个线程。只要在流中添加一个 "parallel":
 
  复制
  Map<CityState, StatsAggregation> stats = inputEntries.stream().parallel().
  1.
  这导致流框架将元素列表细分为多个部分,并同时在单独的线程中运行它们。随着所有不同的线程完成它们的计算,框架将它们串行添加到生成的 Map 中。
 
  在第4行中使用Collectors::groupingByConcurrent而不是Collectors:groupingBy。在这种情况下,框架使用并发映射,允许将来自不同线程的元素直接插入到此映射中,而不必串行组合。

(编辑:PHP编程网 - 黄冈站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读