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

时间:2019-02-07 17:10:28

标签: r merge cartesian-product

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

  1. 一个是人口普查文件,具有700,000多个记录。

    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个带有额外变量的民用寄存器。

此额外变量的值满足条件。条件是人口普查年份(人口普查的变量)大于民事登记册的变量“出生年份”(换句话说,人口普查年份比登记册上的出生年龄年轻)。

正如我所说,目标是制造笛卡尔乘积,但要添加一个额外的变量(标志),当满足条件(普查年份>出生年份)时,变量将给出“ 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'删除那些记录)。

我希望这一点得到很好的解释,并且对其他人也有用...感谢一百万个小费。非常欢迎。

1 个答案:

答案 0 :(得分:1)

将问题与评论一起使用,可以使用data.table软件包实现您的期望。该程序包通过引用进行修改,因此可以帮助减少用于子集,合并和计算的内存量。有关该软件包的更多信息,我建议使用其wikipedia github page,其中包含用于大多数计算的快速备忘单。

下面是一个示例,说明如何使用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