使用Java访问数据集的最快方法是什么?

我有一个包含180万行的数据文件,需要为我正在编写的机器学习程序读取这些数据。数据目前存储在CSV文件中,但显然我可以根据需要将其放入数据库或其他结构中——这些数据不需要定期更新。

我目前使用的代码如下。我首先将数据导入到一个数组列表中,然后将其传递给表模型。这样做非常慢,目前仅执行前10,000行就需要六分钟,这是不可以接受的,因为我需要经常对数据进行不同的算法测试。

我的程序只需要访问每行数据一次,因此没有必要将整个数据集保存在RAM中。我是应该从数据库中读取数据,还是有更快的方法逐行读取CSV文件?

import java.io.File;import java.io.FileNotFoundException;import java.util.ArrayList;import java.util.Scanner;import javax.swing.table.DefaultTableModel;import javax.swing.table.TableModel;public class CSVpaser {public static TableModel parse(File f) throws FileNotFoundException {    ArrayList<String> headers = new ArrayList<String>();    ArrayList<String> oneDdata = new ArrayList<String>();    //获取表的标题。    Scanner lineScan = new Scanner(f);    Scanner s = new Scanner(lineScan.nextLine());    s.useDelimiter(",");    while (s.hasNext()) {        headers.add(s.next());    }    //现在遍历表的每一行,并将每个单元格添加到数组列表中    while (lineScan.hasNextLine()) {       s =  new Scanner(lineScan.nextLine());       s.useDelimiter(", *");       while (s.hasNext()) {           oneDdata.add(s.next());       }    }    String[][] data = new String[oneDdata.size()/headers.size()][headers.size()];    int numberRows = oneDdata.size()/headers.size();    //将数据移动到一个普通数组中,以便可以放入表中。    for (int x = 0; x < numberRows; x++) {        for (int y = 0; y < headers.size(); y++) {            data[x][y] = oneDdata.remove(0);        }    }    //创建一个表并返回它    return new DefaultTableModel(data, headers.toArray());}

更新:根据我收到的回答反馈,我重写了代码,现在运行10,000行只需3秒而不是6分钟,这意味着整个文件只需十分钟…但如果有进一步的加速建议,我将不胜感激:

       //加载数据文件    File f = new File("data/primary_training_short.csv");
    Scanner lineScan = new Scanner(f);    Scanner s = new Scanner(lineScan.nextLine());    s.useDelimiter(",");    //现在遍历结果的每一行    while (lineScan.hasNextLine()) {       s =  new Scanner(lineScan.nextLine());       s.useDelimiter(", *");       String[] data = new String[NUM_COLUMNS];       //从CSV文件中提取数据,以便我可以访问它       int x = 0;       while (s.hasNext()) {           data[x] = (s.next());           x++;       }       //在这里插入每行执行的代码   }

回答:

data[x][y] = oneDdata.remove(0);

这样做效率非常低。每当你从ArrayList中删除第一个条目时,所有其他条目都需要向下移动。

至少你应该创建一个自定义的TableModel,这样就不必复制数据两次了。

如果你想将数据保存在数据库中,那么请在网上搜索ResultSet TableModel。

如果你想保持CSV格式,那么你可以使用ArrayList作为TableModel的数据存储。因此,你的Scanner代码将直接将数据读取到ArrayList中。请参阅List Table Model以获取一种解决方案。或者你可能想使用Bean Table Model

当然,真正的问题是谁有时间浏览所有180万条记录?所以你真的应该使用数据库,并有查询逻辑来过滤从数据库返回的行。

我的程序只需要访问每行数据一次,因此没有必要将整个数据集保存在RAM中

那么你为什么要在JTable中显示它呢?这意味着整个数据将在内存中。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注