【问题标题】:Delete duplicates in large dataset based on condition根据条件删除大型数据集中的重复项
【发布时间】:2017-01-16 11:27:10
【问题描述】:

我想根据条件删除一个非常大的数据集(数百万行)中的重复项。我考虑了以下简化示例来说明我的问题:

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 作为数据集的一部分,我在最新的编辑中添加了它们。分组/过滤并不真正需要它们,但仍然应该是最终结果的一部分)。目前提出的解决方案没有考虑到这一点。

【问题讨论】:

  • 您已将问题标记为“sql”。你用的是什么数据库?
  • 这是一个 SQL 问题吗?如果是,请标记您的 DBMS。
  • 在 R 中,可能是 test[,list(Value=min(Value)),by=list(ID,YEAR,Count)]
  • 通常的指导在这里:stackoverflow.com/a/28481250 是的,您必须考虑哪些数据生成过程可以令人满意地模拟您的真实用例。无论如何,如果您对自己的答案感到满意,那么下次您对性能有疑问时,请记住这一点。无论如何,我的建议是:test[test[, min(Value), by=.(ID, YEAR, Count)], on=c("ID", "YEAR", "Count", Value="V1")](如果我理解正确的话)。
  • @user3032689 在您更改大小写以匹配后,我上一条评论中的代码仍然有效。 (您将 YEAR 切换为 Year,将 Value 切换为 Value,等等...)

标签: r filter duplicates data.table sqldf


【解决方案1】:

在 R 中,您可以通过以下方式回答这个问题:test[,.(Value=min(Value)), by=.(ID, Year, Count)]

在这里,我们将遍历数据并找出 ID、Year 和 Count 的每个组合的最小值。这使用包 data.table 中的 data.table 语法

【讨论】:

  • 完美运行。谢谢。
  • 一个问题:在更大的数据表中,其他对排序不重要的列被丢弃。假设其他列名称称为 A B 和 C,我该如何在您的解决方案中防止这种情况发生?
  • 这取决于您拥有的列。您需要为它们选择一个汇总函数并将它们添加到第一个列表中。或者,如果您想要具有这些值的唯一行,您可以将列名添加到第二个列表(在 by 之后)。 test[,.(Value=min(Value), newVar=sum(newVar), newVar2=max(newVar2)), by=.(ID, Year, Count)]
  • 好的,我尝试设置代码以获取具有这些值的唯一行,但它不起作用。什么是正确的语法?也可以随意编辑您的答案。谢谢!
  • by 命令中变量的顺序不会改变行中的任何值;它只会改变新表中列的顺序。我认为它不会影响行的顺序。
【解决方案2】:

根据需要删除的数据量,我认为有两种可能性。

如果您要删除超过 20% 的数据,最好的选择是创建一个临时表并仅插入您想要保留的行。

否则你可以做一个查询,反正会很长。

对于 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 将执行全表扫描以填充 hastable。 如果您的数据负载不是那么大(大小),您可能想尝试在所有列上创建索引:ID、YEAR、COUNT、VALUE

将SQL计划与两种情况进行比较

【讨论】:

  • 感谢您的参与,也对此表示赞同,因为我想知道 sol 在 sqldf 中的外观 – user3032689 46 分钟前
猜你喜欢
  • 2017-08-29
  • 1970-01-01
  • 2020-02-17
  • 1970-01-01
  • 1970-01-01
  • 2013-08-27
  • 2014-03-14
  • 1970-01-01
相关资源
最近更新 更多