【问题标题】:Efficient way to group indices of the same elements in a list对列表中相同元素的索引进行分组的有效方法
【发布时间】:2019-06-18 03:34:01
【问题描述】:

假设我有一个如下所示的列表:

[1, 2, 2, 5, 8, 3, 3, 9, 0, 1]

现在我想对相同元素的索引进行分组,所以结果应该是这样的:

[[0, 9], [1, 2], [3], [4], [5, 6], [7], [8]]

如何有效地做到这一点?我尽量避免使用循环,所以任何使用 numpy/pandas 函数的实现都很棒。

【问题讨论】:

  • numpy.argsort 后跟一次遍历索引(引用数组元素)以对它们进行分组(在不同元素上断开组)。或使用 itertools.groupby 进行第二步。
  • 你能通过给出一些代码示例来指定“一次通过索引”吗?@randomir
  • 顺序重要吗?另外,你的尝试在哪里?
  • “我尽量避免使用循环”——为什么?
  • @cs95 顺序实际上并不重要。我尽了最大努力,但无法提出一个好的实现(即使使用循环),所以不得不在这里问。

标签: python pandas group-by


【解决方案1】:

使用 pandas GroupBy.apply,这非常简单——使用您的数据对一系列索引进行分组。一个不错的好处是您可以保持索引的顺序。

data = [1, 2, 2, 5, 8, 3, 3, 9, 0, 1]
pd.Series(range(len(data))).groupby(data, sort=False).apply(list).tolist()
# [[0, 9], [1, 2], [3], [4], [5, 6], [7], [8]]

【讨论】:

    【解决方案2】:

    您可以使用collections.defaultdict 对索引进行分组:

    from collections import defaultdict
    
    lst = [1, 2, 2, 5, 8, 3, 3, 9, 0, 1]
    
    d = defaultdict(list)
    for i, x in enumerate(lst):
        d[x].append(i)
    
    print(list(d.values()))
    # [[0, 9], [1, 2], [3], [4], [5, 6], [7], [8]]
    

    这也保持了添加的索引的顺序而不进行排序。

    【讨论】:

      【解决方案3】:

      此解决方案是对哈希计数的修改,但不是计数,而是仅存储找到的值的索引。

      arr = [1,2,2,5,8,3,3,9,0,1]
      d = dict()  
      for i,v in enumerate(arr):  
          d[v] = d.get(v,[]) #use an if-statement to avoid doing this too often
          d[v].append(i) 
      print(d.values()) 
      

      【讨论】:

        【解决方案4】:

        不知道你为什么要“避免循环”,因为没有办法知道你调用的函数没有使用循环,增加了函数调用的开销。

        此外,分组后,您会丢失有关分组内容的信息 - 因此将输出放在 dict 中似乎更有意义。

        这样做:

        from itertools import groupby
        
        l = [1, 2, 2, 5, 8, 3, 3, 9, 0, 1]
        result = {
            key: [item[0] for item in group]
            for key, group in groupby(sorted(enumerate(l), key=lambda x: x[1]), lambda x: x[1])
        }
        
        print(result)
        

        输出:

        {0: [8], 1: [0, 9], 2: [1, 2], 3: [5, 6], 5: [3], 8: [4], 9: [7]}
        

        【讨论】:

        • 我实际上必须在更大的数据集上解决同样的问题。据我所知,pandas/numpy 实现在处理大量数据时可以节省更多。如果这不是真的,请纠正我。
        • 大多数解决方案最终都会将整个数据集加载到内存中。主要关注点是避免在内存中创建太多额外的数据副本。我提供的解决方案不会在结果中创建一个副本之外的多余副本,因为使用的元素都使用生成器。但是,您要求的解决方案似乎与开始时的大型数据集不太一致。在这种情况下,您究竟认为什么是“大”?
        • 我有一个 Pandas 数据框,它有大约 32k 行和 9 列。索引分组沿每一列应用,所以我会说它是一个包含 ~32k 元素的列表
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-21
        • 2023-01-31
        相关资源
        最近更新 更多