使用数据获取Groovy

Groovy是Java的近乎完美的补充,为我的使用提供了一个紧凑,高度表达且兼容的脚本环境。 当然,Groovy并不完全完美。 与任何编程语言一样,其设计基于需要权衡的一系列权衡,才能产生高质量的结果。 但是对我来说,Groovy的优点远大于缺点,这使其成为我的数据分析工具包中不可或缺的一部分。 在一系列文章中,我将解释如何以及为什么。

在1990年代后期,我发现自己对Java编程语言越来越感兴趣,越来越多地将它用于AWK和我以前在C语言中所做的工作。到2005年,低成本和强大Linux的功能说服了我放弃我心爱但老化的Sun工作站。 在我的工作中,AWK, sort(1)paste(1)join(1)在Linux环境中竞争激烈,首先是Perl ,然后是Python 。 Perl的语法从未达到我的口味,但我发现Python引人入胜,因为它的可读性,“包含电池”的理念以及与各种其他内容(如定界文本文件,电子表格,数据库,图形化,除了一件事之外,它并没有给我带来对整个Java Universe的干净,透明的访问,而这对我的工作流越来越重要。

然后我“发现”了Groovy。

分隔的文本文件

在以AWK为中心的数据分析领域中,使用数据通常意味着使用定界的文本文件。 这是由两个因素共同造成的。 首先是Unix文本文件处理工具通常认识到分隔符文本文件中经常遇到数据,即文本文件,其行以换行符分隔,被分隔为字段,并以字段分隔符分隔(例如, TAB或其他一些不寻常的字符,例如竖线)。 第二个原因是电子表格之类的工具倾向于提供一种“导出”功能,该功能可产生逗号分隔的值文本文件,按照惯例,其第一行是每个字段的名称,而其余行则由用逗号分隔的数据字段组成(或者,在使用逗号作为小数点的国家/地区,请使用分号)。

AWK非常擅长处理带分隔符的文本文件,除非字段或行分隔符也出现在数据中。 此外,AWK还确实适合用于编写对呈现的数据做出React的代码节,并且在数据呈现复杂(例如,层次结构)时,吸引力并不那么大。 AWK也不真正提供在不通过中间定界文本格式的情况下从关系数据库,电子表格或二进制格式(例如dBase)中读取或写入数据的任何好方法。

在这里,更完整的编程语言(例如Python或Groovy)开始变得有趣。 但是,在介绍这类直接集成示例之前,我将先回到带分隔符的文本。 让我们写一些代码! 但是首先,让我们获取一些数据! 但是,等等-我们最好先安装Groovy。

Groovy

找出如何安装Groovy的最好方法是转到groovy-lang.org上的安装说明 。 我更喜欢为此目的使用SDKMAN (在安装说明的中间记录),但是您也可以在存储库中安装该版本。 请注意,Java是先决条件。 这些天来,我使用Java8。同样,您可以在存储库中安装该版本。

获取数据

有了Groovy之后,就可以使用浏览器从世界银行站点访问开放的世界人口数据 。 在右侧,您将看到“ 下载”按钮。 以CSV格式获取数据; 它压缩在名为API_SP.POP.TOTL_DS2_en_csv_v2的目录中。 将该目录解压缩到系统上的合适位置。 然后打开一个终端窗口, cd到该目录中。

最后-一些代码!

这是一个简单的Groovy脚本,用于读取您下载的CSV文件之一并将其打印到终端窗口中:



   
   
String mdCountryCSV = "Metadata_Country_API_SP.POP.TOTL_DS2_en_csv_v2.csv"

new File ( mdCountryCSV ) . withReader { reader -& gt ;
    reader. eachLine { line -& gt ;
        println line
    }
}

该脚本很好地概述了Groovy为Java程序员提供的功能。

首先, String mdCountryCSV = ... 这就像Java一样-我们正在声明一个初始化为String文字的String变量。 哦,是的,在大多数情况下,Groovy允许我们删除行尾分号。

接下来, new File(mdCountryCSV).withReader { reader -> ,在四行之后用}其关闭。 new File()部分也和Java一样。 但是,Groovy增强了许多java.lang.*java.io.*java.util.*和标准Java库的其他部分。 在这种情况下,Groovy使用名为withReader的方法增强了File类。 此方法接受闭包作为参数,在这种情况下,我们将其表示为代码块{ reader -> ... }reader ->将闭包的参数定义为变量reader

Groovy的新颖性完成了什么? 从功能withReaderwithReader创建一个Reader实例并调用该实例的关闭代码,并将该实例分配给变量reader ,最后关闭创建的File实例并释放其资源并处理发生的任何错误。 实际上,这使Groovy程序员可以将匿名方法声明为其他方法调用的参数。 而且,在封闭物内部可获得周围环境,而没有任何特殊的场所。

接下来, reader.eachLine { line -> ,在两行之后被}关闭。 再次,我们看到了Groovy增强的Reader方法, eachLine以闭包作为参数调用,在这种情况下,我们用{ line -> ... } 。 在这里, Reader实例为读取的文件的每一行调用闭包。

最后, println line仅打印由Reader实例读取的行。 Groovy在这里向我们展示了可以省略方法调用参数的括号,并且实际上它具有import System.out作为执行代码的序言。

将此代码块另存为ex01.groovy ,与数据保存在同一目录中,并从终端命令行执行以下命令:

groovy ex01.groovy

你看到了什么?

在这一点上,值得注意的是,Groovy还悄悄地取消了可能在执行相同任务的Java程序中需要进行的导入和公共类定义。

处理领域

到目前为止,我们的Groovy脚本已经处理了行定界符,但尚未将行拆分为字段。 快速检查文件Metadata_Country_API_SP.POP.TOTL_DS2_en_csv_v2.csv会发现它是最复杂的CSV文件类型,它使用逗号作为字段分隔符,并引用可以包含字段或行分隔符的字段。

看第三行,关于安哥拉; 在第四个字段中,出现短语“基于国际货币基金组织的数据,国民账户”。 在第9行中,对于阿根廷,不仅逗号出现在同一字段中,而且回车/换行符对也出现。 最后,在第199行中,该字段包含一个双引号字符,该字符显示为两个连续的双引号。 一个“带引号的引号”,不要与两个连续的双引号作为一个字段的唯一内容混淆,这意味着一个空字段。 丑陋!

在AWK中,处理这种杂乱的东西并不令人愉快。 但是,在Groovy中,我们可以使用称为opencsv的高级Java库。 从SourceForge 下载.jar文件 。 将该.jar文件放在Groovy的默认查找路径中,即您的主目录中.groovy / lib子目录中。

在这一点上,第一个程序可以变为现场感知的:



   
   
import com.opencsv.CSVReader

String mdCountryCSV = "Metadata_Country_API_SP.POP.TOTL_DS2_en_csv_v2.csv"

new File ( mdCountryCSV ) . withReader { reader ->
    CSVReader csvReader = new CSVReader ( reader )
    csvReader. each { fields ->
        println fields
    }
}

将此文件另存为ex02.groovy在同一目录中,并使用groovy命令运行它。

这里有什么新消息?

首先,我们必须导入CSVReader功能。 然后我们创建一个CSVReader从传授给我们读者实例withReader 。 最后,我们打印CSVReader实例产生的字段。 在这里,我们使用Groovy放在每个对象上的each方法以及opencsv提供的行拆分以处理文件中的行。 csvReader.each { fields ->将每一行分成几个字段,即字符串数组。 我们可以将第一个字段称为fields[0] ,将第二个fields[1]称为fields[1] ,依此类推。

鉴于这种CSV文件的第一行提供了字段名称,我们可以调整上面的代码以按名称引用字段,如下所示:



   
   
import com.opencsv.CSVReader String mdCountryCSV = "Metadata_Country_API_SP.POP.TOTL_DS2_en_csv_v2.csv" new File ( mdCountryCSV ) . withReader { reader -> CSVReader csvReader = new CSVReader ( reader ) String [ ] csvFieldNames = csvReader. readNext ( ) HashMap fieldValuesByName = new HashMap ( )
    csvReader. each { fieldValuesByNumber ->
        csvFieldNames. eachWithIndex { name, number ->
            fieldValuesByName [ name ] = fieldValuesByNumber [ number ]
        }
        println "fieldValuesByName[ \" Country Code \" ] = " +
            fieldValuesByName [ "Country Code" ] +
            " fieldValuesByName[ \" IncomeGroup \" ] = " +
            fieldValuesByName [ "IncomeGroup" ]
    }
}

将此ex03.groovy另存为ex03.groovy并在同一目录中运行。

在上面的代码中,我们readNextCSVReader实例调用readNext以获取第一条记录,并将字段名称保存在String数组中。 然后,每次读取记录时,我们each对字段名称执行each方法,以将csvReader.each()传递的字段数组中的值复制到映射中,该映射中的键为字段名称,而值来自于记录上的相应字段。

println语句显示我们通过名称访问字段值,例如fieldValuesByName["Country Code"]

接下来要去哪里?

这可能是很多Groovy入门的基础。 以下是增强体验的良好参考:

还提供了大量Groovy书籍,并对语言进行了很好的介绍。

Groovy系列的下一部分将进一步介绍已经介绍的主题:制作最后一个示例groovier,读取多个CSV文件,链接它们的数据以及编写复合/摘要。

您对编写“入门指南”文章有想法吗? 提交您的故事建议

翻译自: https://opensource.com/life/16/10/getting-groovy-data

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值