两个大数据框的笛卡尔积,保持满足条件的值
Cartesian product of two large dataframes, keeping the values that fulfil a condtion
所以我的问题可能很幼稚,但我已经搜索了很长时间,仍然找不到答案。我有两个大数据集:
一个是人口普查档案,有超过70万条记录。
Lastname Census 1stname Census census_year
C2last C2first 1880
C3last C3first 1850
C4last C4first 1850
另一个是由 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.where
、pd.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
所以我的问题可能很幼稚,但我已经搜索了很长时间,仍然找不到答案。我有两个大数据集:
一个是人口普查档案,有超过70万条记录。
Lastname Census 1stname Census census_year C2last C2first 1880 C3last C3first 1850 C4last C4first 1850
另一个是由 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.where
、pd.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