【问题标题】:Number of times two or more numbers appear in the same array两个或更多数字出现在同一个数组中的次数
【发布时间】:2023-01-03 00:02:18
【问题描述】:

我有一系列长度大于 1 的一维数组。 我想在s 中找到同时出现在多个数组中的数字以及它们一起出现在多少个数组中。

import numpy as np
import pandas as pd


a=np.array([1,2,3])

b=np.array([])

c=np.array([2,3,4,5,6])
d=np.array([2,3,4,5,6,9,15])
e=np.arra([5,6])

s=pd.Series([a,b,c,d,e])

在这个例子中,期望的结果会是这样的

{[2,3]:3, [5,6]:3,  [2,3,4,5,6]:2]}

预期结果不需要是字典,而是包含此信息的任何结构。

另外,对于像 s 这样的 >200 系列,我必须这样做,所以性能对我来说也很重要

我试过了

result=s.value_counts()

但我不知道如何进行

【问题讨论】:

  • 你会得到TypeError: unhashable type: 'list',因为列表不能是字典的键
  • 所有可能的长度都需要这个,包括长度 1?
  • @Sala 不包括大于 1 的长度
  • @TalhaTayyab 它可能是一个数据框或任何其他我只对获取该信息感兴趣的结构
  • 数字在列表中的顺序是否重要?

标签: python pandas numpy


【解决方案1】:

我认为你在这里缺少的是一种构建每个数组中存在的数字组合的方法,然后能够计算每个组合出现的次数。为此,您可以使用内置的 itertools module 之类的东西:

from itertools import combinations
import numpy as np

a = np.array([1,2,3])
for c in combinations(a, 2):
    print(c)

>>> (1, 2)
>>> (1, 3)
>>> (2, 3)

因此,使用它,您可以为每个长度构建一个系列,并检查长度为 2 的每个组合发生了多少次,长度为 3 的每个组合发生了多少次等等。

import numpy as np
import pandas as pd

a=np.array([1,2,3])
b=np.array([])
c=np.array([2,3,4,5,6])
d=np.array([2,3,4,5,6,9,15])
e=np.array([5,6])

all_arrays = a, b, c, d, e
maxsize = max(array.size for array in all_arrays)

for length in range(2, maxsize+1):
    length_N_combs = pd.Series(x for array in all_arrays for x in combinations(array, length) if array.size >= length)
    
    counts = length_N_combs.value_counts()
    print(counts[counts>1])

从这里您可以根据需要格式化输出。请注意,您必须排除太短的数组。我正在使用生成器理解来稍微提高效率,但请注意,这个算法无论如何都不会便宜,您需要进行大量比较。生成器推导式是一种将生成器表达式压缩为单行代码的方法(而且不止于此)。在这种情况下,上述嵌套理解大致相当于定义一个生成器,该生成器从 combinations 返回的生成器生成,并调用该生成器来构建 pandas 系列。这样的事情会给你同样的结果:

def length_N_combs_generator(arrays, length):
    for array in arrays:
        if array.size >= length:
            yield from combinations(array, length)

for length in range(2, maxsize+1):
    s = pd.Series(length_N_combs_generator(all_arrays, length))
    counts = s.value_counts()
    print(counts[counts>1])

【讨论】:

  • @泡芙 非常感谢!这似乎有效,但我不完全理解它,因为我不熟悉这种语法。你能用文字简短地描述一下这一行吗? length_N_combs = pd.Series(x for array in all_arrays for x in combinations(array, length) if array.size >= length)
  • 您可以阅读 here 关于列表理解和生成器理解,这是我在这里使用的,以及 here 关于嵌套理解。看看这是否足够,如果不够我可以提供解释。
【解决方案2】:

您可以使用set操作:

from itertools import combinations
from collections import Counter

s2 = s.apply(frozenset).sort_values(key=lambda s: s.str.len(), ascending=False)

c = Counter(x for a,b in combinations(s2, 2) if len(x:=a&b))

# increment all values by 1
for k in c:
    c[k] += 1
    
dict(c)

输出:

{frozenset({2, 3, 4, 5, 6}): 2, frozenset({2, 3}): 3, frozenset({5, 6}): 3}

【讨论】:

    猜你喜欢
    • 2017-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-09
    相关资源
    最近更新 更多