mcpField
X
xsv

xsv

官方Agent-ready
github.com数据库与数据10.8kxsv79 周前更新
代码仓库访问官网

关于 xsv

xsv 是一个高性能的 CSV 处理工具,提供索引、切片、连接和统计分析功能。以 Rust 编写,设计用于高效处理大型 CSV 文件。

主要功能

  1. 01索引和搜索 CSV 文件中的列和行
  2. 02计算统计信息(计数、求和、均值等)
  3. 03连接、拼接和转换多个 CSV 文件

适用场景

  1. 01编码 Agent 在数据处理工作流中高效处理 CSV 文件
  2. 02开发人员分析和转换日志、配置或数据导出文件

安装

选择你的系统或包管理器,复制命令到终端运行。

$
brew install xsv

安装完成后运行xsv --version确认安装成功。

命令示例

常用命令按使用顺序排列。

01
xsv headers data.csv
02
xsv stats data.csv

详细介绍

xsv 现已停止维护

作为 xsv 的替代品,我推荐 qsv 或 xan。


xsv 是一个用于索引、切片、分析、拆分和合并 CSV 文件的命令行程序。命令应当简单、快速且可组合:

  1. 简单任务应当易于完成。
  2. 应在命令行界面中体现性能方面的权衡。
  3. 组合使用不应以牺牲性能为代价。

除了快速浏览几个命令外,本 README 还介绍了如何 安装 xsv。

Linux 构建状态 Windows 构建状态 README 配图

采用 MIT 或 UNLICENSE 双重许可。

可用命令
  • cat - 按行或按列串联 CSV 文件。
  • count - 统计 CSV 文件中的行数。(存在索引时可瞬间完成。)
  • fixlengths - 通过填充或截断记录,强制 CSV 文件中的记录长度一致。
  • flatten - 以扁平格式查看 CSV 记录。适合逐条查看记录。例如:xsv slice -i 5 data.csv | xsv flatten。
  • fmt - 使用不同的分隔符、记录终止符或引号规则重新格式化 CSV 数据。(支持 ASCII 分隔数据。)
  • frequency - 为 CSV 数据的每一列生成频率表。(存在索引时会利用并行处理来加速。)
  • headers - 显示 CSV 数据的标头,或显示多个 CSV 文件之间的共有标头。
  • index - 为 CSV 文件创建索引。速度非常快,并可实现对 CSV 文件的常数时间索引。
  • input - 使用特殊的引号和转义规则读取 CSV 数据。
  • join - 支持内连接、外连接和交叉连接。使用简单的哈希索引来加速。
  • partition - 根据列值对 CSV 数据进行分区。
  • sample - 使用蓄水池抽样从 CSV 数据中随机抽取行(即,所用内存与样本大小成正比)。
  • reverse - 反转 CSV 数据中的行顺序。
  • search - 在 CSV 数据上运行正则表达式。对每个字段单独应用正则表达式,并仅显示匹配的行。
  • select - 从 CSV 数据中选择列或调整列顺序。
  • slice - 从 CSV 文件的任意位置切取行。存在索引时,只需解析切片中的行(而不必解析切片起始位置之前的所有行)。
  • sort - 对 CSV 数据进行排序。
  • split - 将一个 CSV 文件拆分为多个包含 N 个数据块的 CSV 文件。
  • stats - 显示 CSV 文件中每一列的基本类型和统计信息。(例如,均值、标准差、中位数、范围等。)
  • table - 使用 弹性制表位显示 CSV 数据的对齐输出。
快速浏览

假设你正在尝试使用 Data Science Toolkit 中的一些数据,其中包含多个 CSV 文件。也许你对世界各地每座城市的人口数感兴趣。那么就下载数据并开始检查吧:

$ curl -LO https://burntsushi.net/stuff/worldcitiespop.csv
$ xsv headers worldcitiespop.csv
1   Country
2   City
3   AccentCity
4   Region
5   Population
6   Latitude
7   Longitude

接下来,你可能想了解每一列中包含的数据类型概况。stats 命令可以为你完成这项工作:

$ xsv stats worldcitiespop.csv --everything | xsv table
field       type     min            max            min_length  max_length  mean          stddev         median     mode         cardinality
Country     Unicode  ad             zw             2           2                                                   cn           234
City        Unicode   bab el ahmar  Þykkvibaer     1           91                                                  san jose     2351892
AccentCity  Unicode   Bâb el Ahmar  ïn Bou Chella  1           91                                                  San Antonio  2375760
Region      Unicode  00             Z9             0           2                                        13         04           397
Population  Integer  7              31480498       0           8           47719.570634  302885.559204  10779                   28754
Latitude    Float    -54.933333     82.483333      1           12          27.188166     21.952614      32.497222  51.15        1038349
Longitude   Float    -179.983333    180            1           14          37.08886      63.22301       35.28      23.8         1167162

xsv table 命令会将任意 CSV 数据格式化为对齐的列,并使用 elastic tabstops。你会发现,即使是 Unicode 字符,它也能正确对齐。

这条命令在我的机器上大约需要 12 秒,但我们可以通过创建索引并重新运行命令来加快速度:

$ xsv index worldcitiespop.csv
$ xsv stats worldcitiespop.csv --everything | xsv table
...

在我的机器上,这样就缩短到了大约 8 秒。(而创建索引不到 2 秒。)

值得注意的是,另一个 CSV 命令行工具包 中类似的“统计”命令,在同一数据集上生成相似的统计结果大约需要 2 分钟。

创建索引带来的好处不只是更快地收集统计数据。它还能让切片操作变得极快,因为只需解析切片部分。例如,假设你想获取最后 10 条记录:

$ xsv count worldcitiespop.csv
3173958
$ xsv slice worldcitiespop.csv -s 3173948 | xsv table
Country  City               AccentCity         Region  Population  Latitude     Longitude
zw       zibalonkwe         Zibalonkwe         06                  -19.8333333  27.4666667
zw       zibunkululu        Zibunkululu        06                  -19.6666667  27.6166667
zw       ziga               Ziga               06                  -19.2166667  27.4833333
zw       zikamanas village  Zikamanas Village  00                  -18.2166667  27.95
zw       zimbabwe           Zimbabwe           07                  -20.2666667  30.9166667
zw       zimre park         Zimre Park         04                  -17.8661111  31.2136111
zw       ziyakamanas        Ziyakamanas        00                  -18.2166667  27.95
zw       zizalisari         Zizalisari         04                  -17.7588889  31.0105556
zw       zuzumba            Zuzumba            06                  -20.0333333  27.9333333
zw       zvishavane         Zvishavane         07      79876       -20.3333333  30.0333333

这些命令是瞬间完成的,因为它们所需的时间和内存与切片大小成正比(这意味着它们可以扩展到任意大的 CSV 数据)。

换个话题,你可能并不总是想查看 CSV 数据中的每一列。在这种情况下,也许我们只关心国家、城市和人口。那就随机查看 10 行吧:

$ xsv select Country,AccentCity,Population worldcitiespop.csv \
  | xsv sample 10 \
  | xsv table
Country  AccentCity       Population
cn       Guankoushang
za       Klipdrift
ma       Ouled Hammou
fr       Les Gravues
la       Ban Phadèng
de       Lüdenscheid      80045
qa       Umm ash Shubrum
bd       Panditgoan
us       Appleton
ua       Lukashenkivske

哎呀!似乎有些城市没有人口数。这种情况有多普遍?

$ xsv frequency worldcitiespop.csv --limit 5
field,value,count
Country,cn,238985
Country,ru,215938
Country,id,176546
Country,us,141989
Country,ir,123872
City,san jose,328
City,san antonio,320
City,santa rosa,296
City,santa cruz,282
City,san juan,255
AccentCity,San Antonio,317
AccentCity,Santa Rosa,296
AccentCity,Santa Cruz,281
AccentCity,San Juan,254
AccentCity,San Miguel,254
Region,04,159916
Region,02,142158
Region,07,126867
Region,03,122161
Region,05,118441
Population,(NULL),3125978
Population,2310,12
Population,3097,11
Population,983,11
Population,2684,11
Latitude,51.15,777
Latitude,51.083333,772
Latitude,50.933333,769
Latitude,51.116667,769
Latitude,51.133333,767
Longitude,23.8,484
Longitude,23.2,477
Longitude,23.05,476
Longitude,25.3,474
Longitude,23.1,459

(xsv frequency 命令会为 CSV 数据中的每一列生成频率表。这条命令只用了 5 秒。)

看来大多数城市都没有对应的人口数。没关系——我们可以调整之前的命令,只显示有人口数的行:

$ xsv search -s Population '[0-9]' worldcitiespop.csv \
  | xsv select Country,AccentCity,Population \
  | xsv sample 10 \
  | xsv table
Country  AccentCity       Population
es       Barañáin         22264
es       Puerto Real      36946
at       Moosburg         4602
hu       Hejobaba         1949
ru       Polyarnyye Zori  15092
gr       Kandíla          1245
is       Ólafsvík         992
hu       Decs             4210
bg       Sliven           94252
gb       Leatherhead      43544

呃。at 是哪个国家?不知道,不过 Data Science Toolkit 有一个名为 countrynames.csv 的 CSV 文件。我们下载它并执行联接,就能看出这些国家是哪些:

curl -LO https://gist.githubusercontent.com/anonymous/063cb470e56e64e98cf1/raw/98e2589b801f6ca3ff900b01a87fbb7452eb35c7/countrynames.csv
$ xsv headers countrynames.csv
1   Abbrev
2   Country
$ xsv join --no-case  Country sample.csv Abbrev countrynames.csv | xsv table
Country  AccentCity       Population  Abbrev  Country
es       Barañáin         22264       ES      Spain
es       Puerto Real      36946       ES      Spain
at       Moosburg         4602        AT      Austria
hu       Hejobaba         1949        HU      Hungary
ru       Polyarnyye Zori  15092       RU      Russian Federation | Russia
gr       Kandíla          1245        GR      Greece
is       Ólafsvík         992         IS      Iceland
hu       Decs             4210        HU      Hungary
bg       Sliven           94252       BG      Bulgaria
gb       Leatherhead      43544       GB      Great Britain | UK | England | Scotland | Wales | Northern Ireland | United Kingdom

哎呀,现在我们有两列都叫 Country,还有一列不再需要的 Abbrev。使用 xsv select 命令重新排列列,就能轻松解决:

$ xsv join --no-case  Country sample.csv Abbrev countrynames.csv \
  | xsv select 'Country[1],AccentCity,Population' \
  | xsv table
Country                                                                              AccentCity       Population
Spain                                                                                Barañáin         22264
Spain                                                                                Puerto Real      36946
Austria                                                                              Moosburg         4602
Hungary                                                                              Hejobaba         1949
Russian Federation | Russia                                                          Polyarnyye Zori  15092
Greece                                                                               Kandíla          1245
Iceland                                                                              Ólafsvík         992
Hungary                                                                              Decs             4210
Bulgaria                                                                             Sliven           94252
Great Britain | UK | England | Scotland | Wales | Northern Ireland | United Kingdom  Leatherhead      43544

也许我们可以直接对原始 CSV 数据执行这项操作?当然可以——因为 xsv 中的联接速度很快。

$ xsv join --no-case Abbrev countrynames.csv Country worldcitiespop.csv \
  | xsv select '!Abbrev,Country[1]' \
  > worldcitiespop_countrynames.csv
$ xsv sample 10 worldcitiespop_countrynames.csv | xsv table
Country                      City                   AccentCity             Region  Population  Latitude    Longitude
Sri Lanka                    miriswatte             Miriswatte             36                  7.2333333   79.9
Romania                      livezile               Livezile               26      1985        44.512222   22.863333
Indonesia                    tawainalu              Tawainalu              22                  -4.0225     121.9273
Russian Federation | Russia  otar                   Otar                   45                  56.975278   48.305278
France                       le breuil-bois robert  le Breuil-Bois Robert  A8                  48.945567   1.717026
France                       lissac                 Lissac                 B1                  45.103094   1.464927
Albania                      lumalasi               Lumalasi               46                  40.6586111  20.7363889
China                        motzushih              Motzushih              11                  27.65       111.966667
Russian Federation | Russia  svakino                Svakino                69                  55.60211    34.559785
Romania                      tirgu pancesti         Tirgu Pancesti         38                  46.216667   27.1

!Abbrev,Country[1] 语法的意思是“移除 Abbrev 列,并移除第二个 Country 列”。由于我们先与 countrynames.csv 执行了联接,第一个 Country 名称(完整名称)现在已包含在 CSV 数据中。

这条 xsv join 命令在我的机器上大约需要 7 秒。它的高性能得益于为给定的某个 CSV 数据文件构建了一个非常简单的哈希索引。join 命令默认执行内联接,但也支持左、右和全外联接。

安装

可从 Github 下载适用于 Windows、Linux 和 macOS 的二进制文件。

如果你是 macOS Homebrew 用户,可以从 homebrew-core 安装 xsv:

$ brew install xsv

如果你是 macOS MacPorts 用户,可以从官方 ports安装 xsv:

$ sudo port install xsv

如果你是 Nix/NixOS 用户,可以从 nixpkgs 安装 xsv:

$ nix-env -i xsv

或者,也可以通过安装 Cargo(Rust 的包管理器),然后使用 Cargo 安装 xsv,从源代码编译:

cargo install xsv

从此仓库编译的方式也类似:

git clone git://github.com/BurntSushi/xsv
cd xsv
cargo build --release

编译可能需要几分钟,具体取决于你的机器。二进制文件最终会生成在 ./target/release/xsv。

基准测试

我编写了一些关于各种 xsv 命令的非常粗略的基准测试。

动机

以下是对这个项目的一些合理批评:

  1. 你不应该处理 CSV 数据,因为 CSV 是一种糟糕的格式。
  2. 如果你的数据有数 GB,那么 CSV 就不是合适的存储类型。
  3. 各种 SQL 数据库都能提供 xsv 中的所有操作,而且索引支持更加完善,性能也好上无数倍。

我相信还有更多批评,但启动这个项目的契机,是有人交给我一个 40GB 的 CSV 文件。我需要弄清楚其中数据的结构,并想办法将其集成到我们现有的系统中。那时我意识到,我所知道的每一种 CSV 工具都远远不够用。它们要么太慢,要么缺乏足够的灵活性。(我参与的另一个项目包含几十个 CSV 文件。它们都不到 40GB,但本应表示同一类数据。可它们的列和列名各不相同,列名也不直观。实用的 CSV 检查工具在这里至关重要,而且速度必须足够快。)

帮助我完成这项任务的关键功能包括索引、随机采样、搜索、切片和选择列。这些功能都让处理 40GB 的 CSV 数据(或几十个 CSV 文件)变得更容易一些。

仅仅是一次接手一个大型 CSV 文件,就足以让我踏上这段探索之旅。从我与他人的交流来看,这么大的 CSV 数据文件似乎并不少见。因此,我相信仍有空间开发一种有望处理如此大规模数据的工具。

名称冲突

本项目与另一个名称相同的类似项目无关: https://mj.ucw.cz/sw/xsv/

评论

支持 Markdown