JSON & CSV 工具

参考: csvkit docs , jq manual , introducing json , data science in cmd, YAML Ain’t Markup Language



数据格式说明

json 格式

json (JavaScript Object Notation) 是一种文本格式,容易读,便于写;json采用了类似于C语言家族的数据格式,多种语言(C, C++, C#, Java, JavaScript, Perl, Python等)都可以方便地解析和生成这种格式,因此,json作为一种理想的数据交换格式得到广泛应用。

json 基于两种数据结构:

对象:在不同的语言中,它可以是对象(object), 记录(record), 结构(struct), 字典(dictionary), 哈希表(hash table), 有键列表(keyed list), 或者关联数组 (associative array),本文统称之为对象(object),记录格式为{"string1":"value1", "string2":"value2"}

数组:在其它语言中通常就是数组(array),记录格式为[value1, value2]

对象和数组的value可以是字符串、数值、true、false、null,也可以是对象、数组,也就是说这两种结构之间可以相互嵌套。

字符串需要使用双引号""扩起来,可以包含任意长度的unicode字符,以下字符需要转义处理:\"("),\\(\),\/(/),\b(退格),\f(换页),\n(换行),\r(回车),\t(制表符),\u(后接4位十六进制数字)。

json 是一种灵活的格式,虽然没有官方标准,但IETF(Internet Engineering Task Force)的RFC 4627已经被广泛接受。

此外,还有一种常用于存储数据的文件格式:yaml,yaml的实现比json复杂,可读性和扩展性更好一些,表达能力更强,但是兼容性要差一点,不同编程语言之间的数据流转,yaml的解析成本比json高。

csv 格式

csv (Comma-Separated Values) 也是一种文本格式,由任意数目的记录组成,记录间以换行符分隔;每条记录由字段组成,字段多以逗号或制表符分隔。通常,所有记录都有完全相同的字段序列。

csv 格式比json更早,应用更广泛,但也没有形成统一的标准,只有一些简单的规则,如:

每一条记录自成一行,不跨行,不留空行;

可设列名,列名要写在文件第一行;

即使某条记录中有字段为空,也要用分隔符指定其位置;

不支持特殊字符,",要转义。

详细用法可参考IETF RFC 4180

在数据处理领域,目前仍以csv为主要传输和交换格式,其它格式的数据文件通常需要首先转换为csv格式,因此,本文主要介绍基于csv的数据处理工具。

[TOP]


数据准备

数据的获取渠道很多,可以直接从数据库中调取,通过web API导出,使用爬虫工具或网络机器人从互联网抓取,甚至还可以散发调研问卷收集第一手数据。这些数据的形式多样,为了处理方便,我们首先考虑将其转换为csv格式。

数据库主要包括MySQL、PostgreSQL、SQLite等,csvkit套件提供了sql2csv命令,可以直接将这类数据库中的数据导出为csv格式,支持MySQL、Oracle、PostgreSQL、SQLite、微软SQL Server和Sybase。

$ sql2csv --db 'sqlite:///data/user.db' --query 'SELECT * FROM user' > 'WHERE age > 30'

常用的选项还有:-l,标记列号;-H,忽略表头;-v,显示详细的错误信息。

web API导出的数据一般都是json格式,而爬虫抓取到的数据和人工输入的数据更加灵活,可以直接存为csv、SQL、json,也可以是办公领域常见的xls和xlsx,csvkit提供了in2csv,可以将这些数据转换为csv格式。

$ in2csv -e gbk -f json file.json > file.csv

常用的选项有:-f FORMAT,指定输入文件的格式,包括csv、dbf、fixed、geojson、ndjson、xls、xlsx;-s,对于定宽格式数据,需要指定一个模式文件,该文件中包含了每一列的起始位置和宽度;--sheet,指定xlsx文件的sheet名;-e ENCODING,指定编码。

也有些数据存储在html和xml格式的网络文件中,这些数据可以使用scrapexml2json进行转换,但实际用起来发现,这两个工具的通用性并不理想,往往需要对转换后的文件做进一步处理,因此,这种情况下,建议直接使用grepsedawk等工具有针对性地提取所需要的数据。

另外,生产环境中还会用到hdf等格式,本文暂时不涉及此类数据。

[TOP]


数据整理

准备好的数据可能是一个文件,也可能是多个文件;这些文件虽然同为csv格式,但可能因存储形式略有差异而互不兼容。因此,需要对收集的数据进行过滤、置换、合并,这里主要针对csv格式的数据处理,介绍csvkit套件中的几个常用工具。

csv数据的可读性较差,因此下文将频繁使用csvlook将csv数据格式化为更加直观的表格形式。

列的提取和重排

使用csvcut可以实现对列的提取和重排,如:

$ cat uid.csv | csvcut -c uid,name | csvlook

-c,指定提取的列及其排列顺序;-C,指定不提取的列;-x,删除全空的行。

行的过滤

行的过滤可使用csvgrep,如:

$ cat uid.csv | csvgrep -c agree -i -r "0" | csvcut -c uid,name,agree | csvlook

-c,指定需要处理的列;-i,输出不匹配的记录项;-r,指定正则表达式;-m,指定需要匹配的字符串。

csv 文件的垂直拼接

csv 文件的垂直拼接可以使用csvstack,如:

$ csvstack uid-*.csv -n item -g u1,u2 | csvlook

-n,创建一个新列,标记来自不同文件的记录;-g,为来自不同文件的记录指定组名并填充到新创建的列中,需要和-n配合使用,也可以将文件名作为组名,使用--filenames

csv 文件的水平拼接

paste可实现csv文件的水平拼接,如:

$ paste -d, {uidA, uidB, uidC}.csv | csvlook

-d用于指定分隔符。

csv 文件的融合拼接

数据的融合使用csvjoin,如:

$ csvjoin -c gender uid1.csv uid2.csv | sed -n '1p;8,15p' | csvlook

-c,指定融合时所依据的列。

csvsql也可以进行数据的融合,如:

$ csvsql --query 'SELECT i.uid, i.name, i.gender, i.agree FROM uid1 i JOIN uid2 j ON (i.gender = j.gender)' uid1.csv uid2.csv | csvlook

csvsql是一个强大的工具,借助于SQL的语法,可以实现上述所有数据整理工作。关于SQL语法,查看这里

[TOP]


数据分析

数据整理为csv格式后,可以使用excel、origin、matlab、mathematica、R等等进行分析,这些方法各有各的优势,NumPy、SciPy和Matplotlib在处理大数据集方面比较灵活,同时学习成本也不高。

[TOP]


工具指引

csvkit

上文中的很多csv工具都来自csvkit,csvkit 是用python编写的套件,官方手册可以看这里 https://csvkit.readthedocs.org

in2csv 将json、xls、xlsx等格式转为csv格式
sql2csv 导出SQL数据为csv格式
csvclean 检查csv文件中的语法错误
csvcut 截取csv文件中特定的列
csvgrep 截取csv文件中特定的行
csvjoin 合并两个或多个csv文件
csvsort 对csv记录排序
csvstack 垂直合并两个或多个csv文件
csvformat  
csvjson  
csvlook 将csv数据格式化为表格形式输出
csvpy  
csvsql 在csv数据上执行SQL查询,或将csv插入到数据库中
csvstat 打印csv文件中所有列的描述性统计信息


jq

jq是用C编写的json文件处理工具,参见 http://stedolan.github.io/jq/

$ curl https://api.douban.com/v2/book/1220562 | jq '.'

格式化输出json文件的全部内容。

$ curl https://api.douban.com/v2/book/1220562 | jq '.title'

输出json文件中’title’的值。

$ curl https://api.douban.com/v2/event/list?loc=beijing | jq '.events[].owner.name'

输出json文件中’events[]’中所有’owner’下’name’的值。

[TOP]