根据条件删除大型数据集中的重复项
Delete duplicates in large dataset based on condition
我想根据条件删除非常大的数据集(数百万行)中的重复项。我考虑了以下简化示例来说明我的概率:
test <- read.table(
text = "
A 1900 1 10 45tz tztime1 01.06.1900
A 1900 2 9 45tz tztime1 01.06.1900
A 1900 3 8 45tz tztime1 01.06.1900
A 1900 4 7 45tz tztime1 01.06.1900
A 1900 5 6 45tz tztime1 01.06.1900
A 1900 6 5 45tz tztime1 01.06.1900
A 1900 7 4 45tz tztime1 01.06.1900
A 1900 7 10 45tz tztime1 01.06.1900
A 1900 7 9 45tz tztime1 01.06.1900
A 1900 8 3 45tz tztime1 01.06.1900
A 1900 8 10 45tz tztime1 01.06.1900
A 1900 8 9 45tz tztime1 01.06.1900
A 2000 1 10 45tz tztime2 01.06.2000
A 2000 2 9 45tz tztime2 01.06.2000
A 2000 3 8 45tz tztime2 01.06.2000
A 2000 3 10 45tz tztime2 01.06.2000
A 2000 3 9 45tz tztime2 01.06.2000
B 1800 1 10 52fd tztime0 01.06.1800
B 1800 2 9 52fd tztime0 01.06.1800
B 1800 3 8 52fd tztime0 01.06.1800
B 1800 3 10 52fd tztime0 01.06.1800
B 1800 3 9 52fd tztime0 01.06.1800
B 1800 4 7 52fd tztime0 01.06.1800
B 1900 1 10 52fd tztime1 01.06.1900
B 1900 2 9 52fd tztime1 01.06.1900
B 1900 2 10 52fd tztime1 01.06.1900
B 1900 2 9 52fd tztime1 01.06.1900
",header=TRUE)
library(data.table)
setDT(test)
names(test) <- c("ID", "Year", "Count", "value", "A","B","C")
在这个简化的数据集中,我有两个人(A 和 B),他们的年份不同但可能重叠。给出了计数以及值。
我想删除每个 YEAR 和 Count 组中每个 ID 的观察结果,它们是重复的并且满足特定条件(见下文)。例如对于组:
A 1900 7 4
A 1900 7 10
A 1900 7 9
我想删除所有观察值,其值大于每个组中的最小值。在这种情况下,我只想
A 1900 7 4
作为余数。
请注意,我的真实数据集非常大并且有更多的列。因此,如果可能的话,我正在寻找一种内存效率高的解决方案。
我希望你说得够清楚了。如果没有,请随时询问缺少的任何信息。
编辑:我的真实数据集比这里显示的列多很多,所以最后我正在寻找一个显示所有列信息的解决方案(例如,假设在这种情况下还有列 A , B 和 C 作为数据集的一部分,我在最新的编辑中添加了它们。它们并不是 grouping/filtering 真正需要的,但仍然应该是最终结果的一部分)。当前提出的解决方案没有考虑到这一点。
在 R 中,您可以用以下方式回答这个问题:test[,.(Value=min(Value)), by=.(ID, Year, Count)]
在这里,我们将浏览数据并找出每个 ID、Year 和 Count 组合的最小值。这使用包 data.table
中的 data.table 语法
根据需要删除的数据量,我认为有两种可能。
如果您要删除超过 20% 的数据,最好的选择是创建一个临时文件 table 并仅插入您想要保留的行。
否则你可以做一个查询,反正会很长。
对于 sql 部分,您似乎想保留一组的最小值,所以 ..
DELETE FROM my_table A
where exists (
SELECT 1 FROM (
SELECT ID, YEAR, Count, min(value) as min_value
FROM my_table
GROUP BY ID, YEAR, Count) TMP
WHERE TMP.ID = A.ID AND TMP.year = A.year AND TMP.count = A.count AND a.value > tmp.min_value)
由于逻辑上的查询,SGBD 将进行完整的 table 扫描以填充 hastable。
如果您的数据负载不是那么大(大小),您可能想尝试在所有列上创建索引:ID、YEAR、COUNT、VALUE
将SQL计划与两个案例进行比较
我想根据条件删除非常大的数据集(数百万行)中的重复项。我考虑了以下简化示例来说明我的概率:
test <- read.table(
text = "
A 1900 1 10 45tz tztime1 01.06.1900
A 1900 2 9 45tz tztime1 01.06.1900
A 1900 3 8 45tz tztime1 01.06.1900
A 1900 4 7 45tz tztime1 01.06.1900
A 1900 5 6 45tz tztime1 01.06.1900
A 1900 6 5 45tz tztime1 01.06.1900
A 1900 7 4 45tz tztime1 01.06.1900
A 1900 7 10 45tz tztime1 01.06.1900
A 1900 7 9 45tz tztime1 01.06.1900
A 1900 8 3 45tz tztime1 01.06.1900
A 1900 8 10 45tz tztime1 01.06.1900
A 1900 8 9 45tz tztime1 01.06.1900
A 2000 1 10 45tz tztime2 01.06.2000
A 2000 2 9 45tz tztime2 01.06.2000
A 2000 3 8 45tz tztime2 01.06.2000
A 2000 3 10 45tz tztime2 01.06.2000
A 2000 3 9 45tz tztime2 01.06.2000
B 1800 1 10 52fd tztime0 01.06.1800
B 1800 2 9 52fd tztime0 01.06.1800
B 1800 3 8 52fd tztime0 01.06.1800
B 1800 3 10 52fd tztime0 01.06.1800
B 1800 3 9 52fd tztime0 01.06.1800
B 1800 4 7 52fd tztime0 01.06.1800
B 1900 1 10 52fd tztime1 01.06.1900
B 1900 2 9 52fd tztime1 01.06.1900
B 1900 2 10 52fd tztime1 01.06.1900
B 1900 2 9 52fd tztime1 01.06.1900
",header=TRUE)
library(data.table)
setDT(test)
names(test) <- c("ID", "Year", "Count", "value", "A","B","C")
在这个简化的数据集中,我有两个人(A 和 B),他们的年份不同但可能重叠。给出了计数以及值。
我想删除每个 YEAR 和 Count 组中每个 ID 的观察结果,它们是重复的并且满足特定条件(见下文)。例如对于组:
A 1900 7 4
A 1900 7 10
A 1900 7 9
我想删除所有观察值,其值大于每个组中的最小值。在这种情况下,我只想
A 1900 7 4
作为余数。
请注意,我的真实数据集非常大并且有更多的列。因此,如果可能的话,我正在寻找一种内存效率高的解决方案。
我希望你说得够清楚了。如果没有,请随时询问缺少的任何信息。
编辑:我的真实数据集比这里显示的列多很多,所以最后我正在寻找一个显示所有列信息的解决方案(例如,假设在这种情况下还有列 A , B 和 C 作为数据集的一部分,我在最新的编辑中添加了它们。它们并不是 grouping/filtering 真正需要的,但仍然应该是最终结果的一部分)。当前提出的解决方案没有考虑到这一点。
在 R 中,您可以用以下方式回答这个问题:test[,.(Value=min(Value)), by=.(ID, Year, Count)]
在这里,我们将浏览数据并找出每个 ID、Year 和 Count 组合的最小值。这使用包 data.table
中的 data.table 语法根据需要删除的数据量,我认为有两种可能。
如果您要删除超过 20% 的数据,最好的选择是创建一个临时文件 table 并仅插入您想要保留的行。
否则你可以做一个查询,反正会很长。
对于 sql 部分,您似乎想保留一组的最小值,所以 ..
DELETE FROM my_table A
where exists (
SELECT 1 FROM (
SELECT ID, YEAR, Count, min(value) as min_value
FROM my_table
GROUP BY ID, YEAR, Count) TMP
WHERE TMP.ID = A.ID AND TMP.year = A.year AND TMP.count = A.count AND a.value > tmp.min_value)
由于逻辑上的查询,SGBD 将进行完整的 table 扫描以填充 hastable。 如果您的数据负载不是那么大(大小),您可能想尝试在所有列上创建索引:ID、YEAR、COUNT、VALUE
将SQL计划与两个案例进行比较