假设我有一台每秒发送 4 位的机器,我想查看某个位签名随时间发送的次数。
我得到了一个列表的输入列表,其中包含一条随时间变化的位消息。
对于我的输出,我想要一个字典列表,每个位对包含唯一的位对作为键,它出现的时间作为值。
编辑新示例:
例如,以下数据集将代表该数据。水平轴是比特位置,垂直轴是随时间变化的样本。因此对于以下示例,我总共有 4 个位和 6 个样本。
a = [
[0, 0, 1, 1],
[0, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1],
[0, 0, 0, 0],
[1, 0, 1, 0]])
对于这个数据集,我试图计算某个位串出现的次数,这个长度应该可以变化,但对于这个例子,假设我一次做 2 位。
所以第一个样本 [0,0,1,1] 将被分成这个 [00,01,11] 第二个是 [01,11,11] 第三个是 [11,11,11] 等等。生成如下列表:
y = [
[00,01,11],
[01,11,11],
[11,11,11],
[11,11,11],
[00,00,00],
[10,01,10]]
据此,我希望能够对每个唯一签名进行计数,并生成一个字典,其中的键对应于签名,值对应于计数。
字典是这样的
z = [
{'00':2, '01':1, '11':2, '10':1},
{'00':1, '01':2, '11':3},
{'00':1, '11':4], '10':1}]
如果有一个已解析项目的列表,查找计数很容易。然而,从原始数据到解析后的列表是我目前遇到的一些麻烦。我有一个实现,但它本质上是 3 个 for 循环,并且它在大型数据集上运行得非常慢。肯定有更好、更 pythonic 的方法来解决这个问题吗?
稍后我会在我的程序中使用 numpy 进行一些额外的计算,所以我不会反对在这里使用它。
更新: 我一直在环顾其他事物并来到这里。也不确定这是否是最佳解决方案。
import numpy as np
a = np.array([
[0, 0, 1, 1],
[0, 1, 1, 1],
[1, 1, 1, 1]])
my_list = a.astype(str).tolist()
# How many elements each
# list should have
n = 2
# using list comprehension
final = [([''.join(c[i:(i) + n]) for i in range((len(c) + n) // n)]) for c in my_list]
final = [['00', '01', '11'], ['01', '11', '11'], ['11', '11', '11']]
更新 2:
我已经运行了以下实现并测试了速度,这就是我的想法。
在宽度为 2 的 4 位和 4 个样本的小示例上运行数据。
x = [
[0,0,1,1],
[0,1,1,1],
[1,1,1,1]]
我的实现花费了 0.0003 秒
Kasrâmvd 的实现花费了 0.0002 秒
Chris 的实现花费了 0.0002 秒
Paul 的实现用了 0.0243 秒
然而,当针对 64 位和 23,497 个宽度为 2 的样本的实际数据集运行时。我得到了这些结果:
我的实现花费了 1.5302 秒
Kasrâmvd 的实现花费了 0.3913 秒
Chris 的实现花费了 2.0802 秒
Paul 的实现用了 0.0204 秒
最佳答案
这是一种使用卷积的方法。由于快速卷积依赖于 FFT,因此需要使用 float 进行计算,我们有 52 位尾数,53 是我们可以处理的最大模式长度。
import itertools as it
import numpy as np
import scipy.signal as ss
MAX_BITS = np.finfo(float).nmant + 1
def sliding_window(data, width, return_keys=True, return_dict=True, prune_empty=True):
n, m = data.shape
if width > MAX_BITS:
raise ValueError(f"max window width is {MAX_BITS}")
patterns = ss.convolve(data, 1<<np.arange(width)[None], 'valid', 'auto').astype(int)
patterns += np.arange(m-width+1)*(1<<width)
cnts = np.bincount(patterns.ravel(), None, (m-width+1)*(1<<width)).reshape(m-width+1,-1)
if return_keys or return_dict:
keys = np.array([*map("".join, it.product(*width*("01",)))], 'S')
if return_dict:
dt = np.dtype([('key', f'S{width}'), ('value', int)])
aux = np.empty(cnts.shape, dt)
aux['value'] = cnts
aux['key'] = keys
if prune_empty:
i,j = np.where(cnts)
return [*map(dict, np.split(aux[i,j],
i.searchsorted(np.arange(1,m-width+1))))]
return [*map(dict, aux.tolist())]
return keys, cnts
return cnts
example = np.random.randint(0, 2, (10,10))
print(example)
print(sliding_window(example,3))
样本运行:
[[0 1 1 1 0 1 1 1 1 1]
[0 0 1 0 1 0 0 1 0 1]
[0 0 1 0 1 1 1 0 1 1]
[1 1 1 1 1 0 0 0 1 0]
[0 0 0 0 1 1 1 0 0 0]
[1 1 0 0 0 1 0 0 1 1]
[0 1 1 1 0 1 1 1 1 1]
[0 1 0 0 0 1 1 0 0 1]
[1 0 1 1 0 1 1 0 1 0]
[0 0 1 1 0 1 0 1 0 0]]
[{b'000': 1, b'001': 3, b'010': 1, b'011': 2, b'101': 1, b'110': 1, b'111': 1}, {b'000': 1, b'010': 2, b'011': 2, b'100': 2, b'111': 3}, {b'000': 2, b'001': 1, b'101': 2, b'110': 4, b'111': 1}, {b'001': 2, b'010': 1, b'011': 2, b'101': 4, b'110': 1}, {b'010': 2, b'011': 4, b'100': 2, b'111': 2}, {b'000': 1, b'001': 1, b'100': 1, b'101': 1, b'110': 4, b'111': 2}, {b'001': 2, b'010': 2, b'100': 2, b'101': 2, b'111': 2}, {b'000': 1, b'001': 1, b'010': 2, b'011': 2, b'100': 1, b'101': 1, b'111': 2}]
关于python - 如何解析列表的列表并将元素一起分析以查看它们随时间出现了多少次?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56640323/