R - 有效地对大量数据进行排序 - 内存问题

时间:2016-04-09 19:38:07

标签: r sorting data-processing

强制性系统设置,以防有助于: 运行Windows 10,R 3.2.3 英特尔酷睿i7 2600k。 16 GB RAM。 R被设置为可以访问所需的RAM。

您好!

我有几百个文件,每个文件都有一个大小为Nx29或Nx31的数据框。

我正在组合~4列,这些列在每个数据帧中重叠。 所以ID1,ID2,日期,文字。我按日期排序。

问题是,这些N在某些文件中可能只有几十行,在其他文件中可能有几百行。

我最初的想法是

Create a blank data frame
Loop -->
    Open a file
    Add that file to the Dataframe.
    Remove any duplicate rows (they happen semi-frequently)
    Open the next file.

然而,即使这样做也会导致我的数据框变得太大而内存不足。

我会考虑写入文件,但这可能有问题,因为我们说我

Read file
Write to file
Open next file
Repeat.

然后,一旦我将所有内容都放在一个大文件中,我可能无法将其加载到R中,因为如果单个组件不能同时存储在内存中,则可能组合也不会。

但是,我希望它按日期排序,每个文件可以包含约45天左右的数据,所以很难看到这样做的方法。

那么如何才能有效地将我的所有数据放在一起,以便能够在不升级R的情况下对其进行排序?

谢谢!

2 个答案:

答案 0 :(得分:0)

一种可能性是使用以下方法 行,我假设你已经有一个列表/向量 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> ,指定您要打开的所有文件。

  1. 创建一个读取文件的辅助函数@EnableJpaRepositories 并返回一个包含两列的矩阵:一列指定 有关my_files的信息,以及包含行号的信息, 但有一个问题是my_inspect用于你想要跳过的行 (后者是例如重复的行)。它也许可以 也是一个想法,添加一个额外的步骤,只有行 稍后将包括将保留,以及这些排序的位置 根据日期。

  2. Date上使用-1功能lapply, 并且您将获得一个列表,其中包含您需要的日期信息 为了在最后对信息进行排序。

  3. 如果my_filenames创建的矩阵已排序 日期,识别文件应该是一个相当简单的任务 具有第一个日期,并且一些循环结构可以例如是 用于处理文件,提取匹配的行 正在调查的日期,然后将这些行保存到新文件。

  4. 这种方法可能不是最有效的方法,但我认为 应该有可能以这种方式完成它。你可能还是 需要将结果分成几个文件,如果是这样的话 添加一个可以通知您的簿记文件可能是一个想法 关于不同文件包含的日期范围的代码。

答案 1 :(得分:0)

如果没有关于数据文件和代码的更多信息,很难提供更具体的分析,但我将演示如何解决这个问题。

首先,关于将数据文件读入R会话,我发现有时候data.table包中的fread()函数比read.table()包更加高效和灵活。基础R提供的{1}} / read.csv() / read.csv2()系列。此外,由于使用data.table对象通常比普通data.frame对象提供了性能优势,因此对于许多类型的操作, 当你处理大数据时,我强烈建议你在R编码时进入data.table世界。

这里我生成一些测试数据,特别是5 data.tables:

library(data.table);

## generate data
set.seed(0L);
NR <- 10L; NF <- 5L;
for (f in seq_len(NF)) {
    n <- paste0('dt',f);
    assign(n,cbind(
        data.table(
            ID1=sample(1:100,NR),
            ID2=sample(1:100,NR),
            Date=sample(seq(as.Date('2016-01-01'),as.Date('2016-12-31'),1L),NR),
            Text=n
        ),
        replicate(sample(10:15,1L),sample(seq_len(NR))) ## varying column set
    ));
};
dt1; ## just generated 5 of these
##     ID1 ID2       Date Text V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12
##  1:  90   7 2016-10-11  dt1  5  9  5 10  4  5  3  7 10  10   6   7
##  2:  27  21 2016-12-07  dt1  6  6  8  3  8  7  1  4  7   5   1   6
##  3:  37  18 2016-03-18  dt1  4  7  4  4  3  4  6  3  3   4   9   2
##  4:  56  67 2016-08-24  dt1  2  4  2  9  9  3  7 10  4   2   5   8
##  5:  88  37 2016-02-15  dt1 10  8  1  8  7 10  5  9  1   9  10   5
##  6:  20  74 2016-04-06  dt1  8 10  6  2  5  2  4  2  6   3   3   3
##  7:  85  47 2016-05-19  dt1  9  1  7  5 10  9  2  1  8   6   7   1
##  8:  96  97 2016-01-05  dt1  1  2  9  7  2  1  8  5  5   1   2   9
##  9:  61  92 2016-05-16  dt1  7  3  3  1  6  8 10  8  9   8   4   4
## 10:  58  35 2016-11-06  dt1  3  5 10  6  1  6  9  6  2   7   8  10

现在将data.table对象写入磁盘文件:

## write files
for (f in seq_len(NF)) {
    n <- paste0('dt',f);
    write.table(get(n),paste0(n,'.txt'),row.names=F);
};

以下代码可用于将磁盘文件读入单个data.table对象。我正在使用select的{​​{1}}参数来排除我们感兴趣的4列以外的所有列,这对于提高效率和减轻RAM负载非常重要。它还确保fread()调用不会因参数中的列集不一致而失败。

rbind()

最后,我们可以按## read files into single data.table fns <- list.files(pattern='^dt.*\\.txt$'); fns; ## [1] "dt1.txt" "dt2.txt" "dt3.txt" "dt4.txt" "dt5.txt" sel <- c('ID1','ID2','Date','Text'); dt <- do.call(rbind,lapply(fns,function(fn) fread(fn,select=sel))); 列对data.table进行排序,如下所示:

Date