两个大数据框的笛卡尔积,保持满足条件的值

Cartesian product of two large dataframes, keeping the values that fulfil a condtion

所以我的问题可能很幼稚,但我已经搜索了很长时间,仍然找不到答案。我有两个大数据集:

  1. 一个是人口普查档案,有超过70万条记录。

    Lastname Census     1stname Census     census_year                
    C2last                C2first            1880
    C3last                C3first            1850
    C4last                C4first            1850
    
  2. 另一个是由 80,000 个观察值组成的民事登记样本。

    Lastname Reg      1stname reg       birth_year               
    P2Last              P2first         1818
    P3last              P3first         1879
    P4last              P4first         1903
    

我需要对两个数据集进行笛卡尔乘积,这显然是一个巨大的文件 (700,000 x 80,000),对于人口普查的每一行,我们应该添加带有额外变量的 80,000 个民事登记册。

这个额外变量的值满足一个条件。条件是人口普查年份(人口普查的一个变量)大于民事登记的变量'year of birth'(或者,换句话说,人口普查年份小于登记簿上的出生)。

正如我所说,目标是制作笛卡尔积,但添加一个额外的变量(标志),当满足条件(人口普查年份>出生年份)时给出'1'或'0',当这不是:

LastNCens  1stNCens   cens_year  LastNamReg   1stNamReg       birth      Flag
C2last     C2first         1880      P2Last     P2first        1818         1
                                     P3last     P3first        1879         1
                                     P4last     P4first        1903         0
C3last     C3first         1850      P2Last     P2first        1818         1
                                     P3last     P3first        1879         0
                                     P4last     P4first        1903         0
C4last     C4first         1860      P2Last     P2first        1818         1
                                     P3last     P3first        1879         0
                                     P4last     P4first        1903         0

这一切,记住产品太大了。

我尝试了很多东西(比较、差异、相交),我还阅读了其他我无法应用的东西(df.wherepd.merge),但它们没有做我需要的,我不能在这里使用它们。我的简单方法是:

cp <-  merge(census, register,by=NULL);

final.dataframe <- cp [which (cp$census_year > cp$birth_year_hsn ),]

但是 R 内存不足。

不言而喻,结果数据框(笛卡尔积)也只对那些标记为“1”的记录有效(去掉带有 Flag='0' 的记录)。

我希望这得到很好的解释并且对其他人也有用......感谢任何提示。非常欢迎。

伴随着对问题的评论,可以使用 data.table 包实现您想要的东西。该包通过引用进行修改,因此可以帮助减少用于子集、合并和计算的内存量。有关该软件包的更多信息,我建议使用他们的 wikipedia github page,其中包含用于大多数计算的快速作弊-sheet。

下面是一个示例,说明如何使用 data.table 执行您正在寻找的那种合并。它被称为 non-equi join。 一些 注释 data.table 包中似乎存在错误,尚未注意到。 by = .EACHI 当您输出两个连接的列时似乎是必要的,以便获得连接左侧部分的原始值。不过也是一笔不小的开销。

df1 <- fread("Lastname_Census     firstname_Census     census_year                
              C2last                C2first            1880
              C3last                C3first            1850
              C4last                C4first            1850", key = "census_year")
df2 <- fread("Lastname_Reg      firstname_reg       birth_year               
              P2Last              P2first         1818
              P3last              P3first         1879
              P4last              P4first         1903", key = "birth_year")

cart_join <- 
    df2[df1, #join df1 on df2
      on = .(birth_year >= census_year), #join criteria
      #Force keep all columns to keep (i.var, indicates to keep var from df1)
      j = .(i.Lastname_Census,
            i.firstname_Census, 
            Lastname_Reg, 
            firstname_reg, 
            birth_year, 
            i.census_year, 
            Flag = birth_year >= i.census_year), 
      #Force evaluation on each i. This will keep the correct birth_year (seems to be a bug)
      by = .EACHI,
      #Let the table grow beyond nrow(df1) + nrow(df2) 
      allow.cartesian = TRUE][,-1] #Remove the first column. It is a merge column

编辑(一些可能的错误)

在尝试连接之后,我注意到了一些不规则之处,并通过打开一个问题来跟进here。请注意,您应该小心我上面建议的答案。从两个表返回值时似乎工作正常(除了 on 语句中曾经使用过的值),但它并非坚不可摧。 详情请参考我的open issue