1. 什么是tablesaw
Tablesaw是一款Java的数据可视化库,主要包括两部分:
- 数据解析库,主要用于家在数据,对数据进行操作(转化、过滤、汇总等),类比Python中的Pandas库;
- 数据可视化库,将目标哦数据转化为可视化的图标,类比Python中的Matplotlib库
与Pandas不同的是,Tablesaw中的表格以列(column)为基本单位,因此大部份操作都是基于列进行的,当然也包括部分对航操作的函数,但是功能比较有限。
从官方文档中可以看到Tablesaw支持的导入和导出的类型:
Format | Import | Export |
---|---|---|
CSV (and other delimited text) | Yes | Yes |
JSON | Yes | Yes |
RDBMS (via JDBC) | Yes | |
Fixed Width Text | Yes | Yes |
Excel | Yes | |
HTML | Yes | Yes |
1.1 tablesaw 工程结构
aggregate
: maven的项目父级项目,主要定义项目打包的配置
breakerx
: tablesaw库的注册中心,主要注册表和列core
: tablesaw库的核心代码,主要是数据的加工处理操作:数据的追加、排序、分组、查询等
data
: 项目测试数据目录
docs
: 项目Markdown文档目录
docs-src
: 项目文档源码目录,主要作用是生成markdown文档
excel
: 解析Excel文件数据的子项目
html
: 解析html文件数据的子项目
json
: 解析json 文件数据的子项目
jsplot
: 数据可视化的子项目,主要作用家在数据生成可视化图表
saw
: tablessaw读写图表数据的子项目
2. 示例代码
使用Springboot继承tablesaw
插件加工和处理而为数据,并可视化
引入依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>springBootDemo</artifactId>
<groupId>com.ygb</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>tablesaw</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>tech.tablesaw</groupId>
<artifactId>tablesaw-core</artifactId>
<version>0.43.1</version>
</dependency>
<dependency>
<groupId>tech.tablesaw</groupId>
<artifactId>tablesaw-jsplot</artifactId>
<version>0.43.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
</dependencies>
</project>添加配置
1
2
3
4
5
6
7
8
9server:
port: 8088
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://127.0.0.1:3306/tablesaw?characterEncoding=UTF-8&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: xiaoyuge读取csv数据
1
2
3
4
5
6
public void before() throws IOException {
log.info("init some data");
tornadoes = Table.read().csv("/Users/xiaoyuge/Desktop/teblesaw-test.csv");
}
打印列名
1
2
3
4
public void columnNames() throws IOException {
System.out.println(tornadoes.columnNames());
}查看shape
1
2
3
4
public void shape() throws IOException {
System.out.println(tornadoes.shape());
}
查看表结构
1
2
3
4
public void structure() throws IOException {
System.out.println(tornadoes.structure().printAll());
}表结构过滤
1
2
3
4
5
6
7
public void structurefilter() throws IOException {
System.out.println( tornadoes
.structure()
.where(tornadoes.structure().stringColumn("Column Type").isEqualTo("DOUBLE")));
}数据预览
1
2
3
4
5
public void previewdata() throws IOException {
System.out.println(tornadoes.first(3));
}列操作
1
2
3
4
5
6
7
8
public void ColumnOperate() throws IOException {
StringColumn month = tornadoes.dateColumn("Date").month();
tornadoes.addColumns(month);
System.out.println(tornadoes.first(3));
tornadoes.removeColumns("State No");
System.out.println(tornadoes.first(3));
}排序
1
2
3
4
5
public void sort() throws IOException {
tornadoes.sortOn("-Fatalities");
System.out.println(tornadoes.first(20));
}
- 汇总
1
2
3
4
public void summary() throws IOException {
System.out.println( tornadoes.column("Fatalities").summary().print());
}
数据过滤
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void filter() throws IOException {
Table result = tornadoes.where(tornadoes.intColumn("Fatalities").isGreaterThan(0));
result = tornadoes.where(result.dateColumn("Date").isInApril());
result =
tornadoes.where(
result
.intColumn("Width")
.isGreaterThan(300) // 300 yards
.or(result.doubleColumn("Length").isGreaterThan(10))); // 10 miles
result = result.select("State", "Date");
System.out.println(result);
}写入文件
1
2
3
4
public void write() throws IOException {
tornadoes.write().csv("rev_tornadoes_1950-2014-test.csv");
}
- 从mysql读取数据
1
2
3
4
5
6
7
8
9
10
11
12
private JdbcTemplate jdbcTemplate;
public void datafrommysql() throws IOException {
Table table = jdbcTemplate.query("SELECT user_id,username,age from user_info", new ResultSetExtractor<Table>() {
public Table extractData(ResultSet resultSet) throws SQLException, DataAccessException {
return Table.read().db(resultSet);
}
});
System.out.println(table);
}
3. 数据可视化
1 | package com.ygb.tablesaw; |
结果如下图:
4. 常用API
4.1 列操作
Tablesaw中的列包括很多数据类型,常用的包括:字符串列(StringColumn)、整型列(IntColumn)、浮点列(DoubleColumn)、日期时间列(DateTimeColumn)等,每一种列提供的API都大同小异
创建列
1 | /*1. 创建一个空列*/ |
添加、编辑和删除数据
1 | /*添加数据*/ |
通用API
1 | name() // 返回列名 |
筛选
1 | double[] values = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; |
筛选出想要的列
1
2
3
4
5//筛选的第一步操作是创建一个表达式,比如我想筛选出所有大于5的数:
Selection limit = column.isGreaterThan(5);
//然后使用where过滤
DoubleColumn column_new = column.where(limit);有条件的编辑数据
1
2
3
4
5
6
7//比如我们想替换所有大于5的数为100,那么可以:
Selection limit = doublecolumn.isGreaterThan(5);
doublecolumn.set(limit, 100.0);
//比如我们可以将所有缺失值设置为平均值:
double avg = doubleColumn.mean();
doubleColumn.set(doubleColumn.isMissing(), avg)
输出列
将列输出到终端显示:
1 | System.out.println(doublecolumn.print()); |
4.2 表格操作
Tablesaw由大量创建、查询、操作、显示和保存表的方法,而且对表的许多操作都会返回其他表。例如:当要求一个表描述器结构时,它回返回一个包含列名、类型和顺序的新表
创建表格(导入文件)
1 | /*方式一:添加列到表格中*/ |
当我们想从文件中导入表格时,我建议采用以下方法:
1 | Table.read().file(File file); |
采用这种方式可以既可以导入.csv格式的文件,也可以导入.xlsx和.xls格式的文件,但是这种方式不能指定导入文件的sheet,如果想要指定sheet,采用下面这种方法:
1 | Table cap = Table.read().usingOptions(XlsxReadOptions |
添加、删除和选择列
- 添加列需要注意的是,新添加的列必须为空,或者与表中的其他列具有相同数量的元素
1
2
3
4
5//可以向表中添加一列或者多列addColumns()方法
t.addColumns(aColmun...)
//还可以通过提供索引来指定在特定位置插入列:
t.addColumn(3, aColumn);
删除列
删除一列或多列
1
2t.removeColumns(int... columnindexs);
t.removecolumns(String columnNames);或者指定想要保存的列,删除其他列,但是这种操作会在原列上进行,如果想要选择某几列而不改变原始数据,建议使用下面的选择列:
1
2t.retainColumns(int... columnindexes)
t.retainColumns(String... columnnames)选择列
当前官方文档中选择列给出的是
select()
函数,但是建议使用selectColumns()
,因为前者不能通过指定index来选择列,而后者可以根据名称和index选择:1
2Table t2 = t.selectColumns("column1");
Table t2 = t.selectColumns(0);也可以通过在当前表格中指定不需要的列来创建新表格,这可能会节省一些键入时间,同样这个函数也可以用名称和index来指定列:
1
2Table t2 = t.rejectColumns("column1");
Table t2 = t.rejectColumns(0);如果只选择一列,通常需要将返回的列转换为更具体的类型。例如:
1
DoubleColumn dc = t.doubleColumn();
拼接表格
拼接表格有两种形式,一种是横向拼接,也就是行数相同,增加列数;另一种是纵向拼接,也就是列数相同,增加行
1 | /*1. 横向组合*/ |
需要注意的是,横向拼接时两个表格的列名不能有重复,纵向拼接时对应列的列名必须相同。
筛选
筛选是在列筛选的基础上进行的,我们以下面这个表格为例:
1 | LocalDate currentdate = LocalDate.of(Integer.parseInt("2024"), 1, 1); |
1 | a |
这里将筛选出2022年1月5日以后的数据。
1 | //选择我们想要筛选的列 |
1 | a |
筛选时我们也可以同时指定多个约束,比如我想要筛选出2022年1月5日以后并且value大于7的数据:
1 | DateColumn date_column = t.dateColumn(0); |
1 | a |
输出表格
将表格输出到终端显示
1 | System.out.println(t.print()); |
导出表格
1 | //表格只能导出为.csv格式 |
5. 技术分析
5.1 数据操作
Tablesaw基于DataFrame概念,允许用户以表格形式存储和操作数据。DataFrame可以看作是一种表格,包含行和列,每一列都有特定的数据类型,可以轻松地添加、删除列,或者根据条件筛选
5.2 API涉及
Tablesaw的API设计注重简介和一致性。大多数功能可以通过链式调用来实现,比如:
1 | Table table = Csv.read("data.csv").usingColumns(ColTypes.STRING, ColTypes.DOUBLE); |
这种设计是的代码更加易读和编写
5.3 统计分析与可视化
Tablesaw内置了各种统计函数,例如计算平均值、中位数、标准差等,此外,还集成了JFreeChart,可以直接生成图标,便于数据可视化
1 | StatSummary summary = table.stats(); |
5.4 扩展性
Tablesaw是模块化的,意味着只引入需要的部分,避免不必要的依赖,它还提供了插件系统,允许你自定义行为和添加新功能
6. 应用场景
数据清洗与预处理: 快速导入数据并进行基本清洗
快速原型开发: 对数据集进行实验性分析,验证假设
教学与学习:在Java环境中教授数据分析原理
特点概述:
- 简单易用: 直观的API,使数据操作变简单
- 性能优化:设计时考虑到大规模数据处理的效率
- 多源数据支持: 支持csv、Excel,甚至数据库和网络数据源
- 强大统计功能: 内置的共计方法和可视化选项
- 模块化和可扩展性: 灵活的架构,易于扩展