【问题标题】:how to append the rows using indexing (or any other method)?如何使用索引(或任何其他方法)附加行?
【发布时间】:2019-11-23 04:59:31
【问题描述】:

我有一个包含 6 列和 450 万行的数据集,我想遍历所有数据集,以比较我的数据集中每一行的最后一列的值和第一列的值并将最后一列值与行的第一列的值匹配的行附加到该行。第一列和最后一列被索引,但没有一个是整数。

我在 stackoverflow 中问了同样的问题,并得到了一个很好的答案,它基于 numpy 和排列数据,但我担心对于相当大的数据集来说它太慢了。

假设这是我的数据集(在真实数据集中,第一个和最后一个元素不是整数):

x = [['2', 'Jack', '8'],['1', 'Ali', '2'],['4' , 'sgee' , '1'],
['5' , 'gabe' , '2'],['100' , 'Jack' , '6'],
['7' , 'Ali' , '2'],['8' , 'nobody' , '20'],['9' , 'Al', '10']] 

结果应该是这样的:

[['2', 'Jack', '8', '1', 'Ali', '2', '5' , 'gabe' , '2','7' , 'Ali' , '2'],
 ['1', 'Ali', '2', '4' , 'sgee' , '1'],
['8' , 'nobody' , '20', '2', 'Jack', '8']]

我认为我可以使用索引来加快处理过程,但我对数据库的了解非常有限。有人有解决方案(使用索引或任何其他工具)吗?

这个问题的 numpy 解决方案如下: How to compare two columns from the same data set?

这里是 sqlite 中真实数据示例的链接:https://drive.google.com/open?id=11w-o4twH-hyRaX8KKvFLL6dQtkTKCJky

【问题讨论】:

  • 你的数据是在sql数据库还是python列表中?
  • 我有.csv.sqlite两种格式
  • 那么您应该包括 sqlite 表定义、任何现有索引以及到目前为止您尝试过的查询和代码。
  • 请注意,sql 查询不能返回可变数量的列,但是您可以轻松地以一种在 python 中构建任意长度的相关行列表的方式轻松地返回行。
  • 为什么你说你有六列,但样本列表似乎有三列?

标签: database sqlite indexing


【解决方案1】:

一个潜在的基于 SQL 的解决方案可能如下所示(我使用您的大型示例数据库作为参考):

为了使我提出的解决方案高效,我将执行以下操作:

在最后一列上创建索引并创建部分索引以消除第一列和最后一列相同的行。这是可选的,因此如果您认为这会导致问题,您可以从后面的查询中删除它。但是如果你这样做了,你应该在 col 0 上创建一个完整的索引。为了完整起见,所有三个都包含在此处。

CREATE INDEX [index_my_tab_A] ON [tab]([0]);
CREATE INDEX [index_my_tab_B] ON [tab]([5]);
CREATE INDEX [index_my_tab_AB] ON [tab]([0]) where [0] != [5];
ANALYZE;

然后我会利用加入行为来生成您需要的列表,以产生您所追求的结果。通过将表连接到自身,您可以获得所考虑的每一行的多个返回行。

SELECT * from tab t1
JOIN tab t2 on t2.[5] = t1.[0] 
WHERE t1.[0] != t1.[5]
AND t2.[5] != 'N/A' -- Optional
ORDER by t1.[0];

在我的机器上针对您的大型示例数据库运行该 SQL(在 ANALYZE 步骤完成后)花费了 0.2 秒。它产生了三行匹配,我认为是正确的。 结果表的含义可能不是很明显,因此这是针对您在原始帖子中提供的小样本运行上述查询时给出的结果。 (该 SQL 被稍微修改以处理减少的列数)……运行时它产生了以下结果,这与您最初想要的结果等效:

1  Ali      2   4   sgee   1
2  Jack     8   1   Ali    2
2  Jack     8   5   gabe   2
2  Jack     8   7   Ali    2
8  Nobody  20   2   Jack   8

您所要做的就是遍历这个结果列表并组合这些行以生成您指定的列表。这里的总体思路是将第二个条目三重奏添加到第一个条目三重奏中,直到第一个条目三重奏发生更改,但仅将第一个条目三重奏包含一次。

因此,从第一行开始,您可以将 Ali trio 与 sgee trio 结合起来,得到 ['1', 'Ali', '2', '4' , 'sgee' , '1']

然后,您将组合三个 Jack 行,给出 ['2', 'Jack', '8', '1', 'Ali', '2', '5' , 'gabe' , '2', '7' , '阿里' , '2']

然后最后一行合并形成 ['8' , 'nobody' , '20', '2', 'Jack', '8']

这匹配您指定的三个数组(尽管顺序不同)

注意:您最初的问题并未表明您对第一列和最后一列在同一行中匹配的情况的预期结果... [3, George, 3] 所以... where 子句消除了两种条目。我注意到在您的大样本数据中,当 col 0 和 col 5 相同时,有很多行。因此 where 子句将这些行排除在考虑之外。我注意到的第二件事是很多行在第 5 列中有“N/A”,所以我也将它们从考虑中删除。

【讨论】:

  • 您的解决方案将我的计算时间从大约 18 天减少到几秒钟!您能否还教育我应该如何“遍历此结果列表并组合行以生成列表”?另外,我应该如何保存结果?
  • @Pie-ton 您可以将结果保存在具有 12 列的新表中(与您的大型数据库匹配)。上面提供的 SQL 查询可以用作使用“INSERT INTO resulttable SELECT ...”语句的输入值集。
  • @Pie-ton 我想我试图解释运行结果列表的步骤。总体思路是枚举左侧的值分组,每次该位置的值发生变化时,您都已到达匹配集的末尾。
猜你喜欢
  • 2011-09-26
  • 2019-02-12
  • 1970-01-01
  • 2020-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多