Python 如何解析列表并一起分析元素,以查看它们随时间发生的次数?
比如说,我有一台每秒发送4位的机器,我想看看一段时间内某个位签名被发送的次数 我得到了一个列表的输入列表,其中包含一条消息,其位随时间变化 对于我的输出,我想要一个字典列表,每个位对,包含唯一的位对作为键和它作为值出现的时间 编辑新示例: 例如,以下数据集就是该数据的表示。水平轴为钻头位置,垂直轴为随时间变化的样本。对于下面的例子,我有4个总比特和6个总样本Python 如何解析列表并一起分析元素,以查看它们随时间发生的次数?,python,python-3.x,list,numpy,binary,Python,Python 3.x,List,Numpy,Binary,比如说,我有一台每秒发送4位的机器,我想看看一段时间内某个位签名被发送的次数 我得到了一个列表的输入列表,其中包含一条消息,其位随时间变化 对于我的输出,我想要一个字典列表,每个位对,包含唯一的位对作为键和它作为值出现的时间 编辑新示例: 例如,以下数据集就是该数据的表示。水平轴为钻头位置,垂直轴为随时间变化的样本。对于下面的例子,我有4个总比特和6个总样本 a=[ [0, 0, 1, 1], [0, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1], [0, 0, 0,
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循环,在大型数据集上运行非常慢。肯定有更好更像蟒蛇的方法来解决这个问题
我将在稍后的程序中使用numpy进行一些额外的计算,所以我不会反对在这里使用它
更新:
我一直在看其他的事情,并得出了这个结论。也不确定这是否是最好的解决方案
将numpy导入为np
a=np.array([
[0, 0, 1, 1],
[0, 1, 1, 1],
[1, 1, 1, 1]])
my_list=a.astype(str).tolist()
#每个元素有多少个
#名单上应该有
n=2
#使用列表理解
final=[([''.join(c[i:+i)+n])表示我的列表中的c在范围内((len(c)+n)//n)])
最终值=['00','01','11'],['01','11','11'],['11','11']]
更新2:
我已经运行了以下实现并测试了它们的速度,下面是我的想法
在4位和4个样本(宽度为2)的小示例上运行数据
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秒
- 我的实现耗时1.5302秒
- Kasr–mvd的实现耗时0.3913秒
- Chris的实施耗时2.0802秒
- Paul的实施耗时0.0204秒
from collections import Counter
x = [[0,0,1,1],
[0,1,1,1],
[1,1,1,1]]
y = [[''.join(map(str, ref[j:j+2])) for j in range(len(x[0])-1)] \
for ref in x]
for bit in y:
d = Counter(bit)
print(d)
印刷品
Counter({'00': 1, '01': 1, '11': 1})
Counter({'11': 2, '01': 1})
Counter({'11': 3})
编辑:要将窗口从2增加到3,可以将以下内容添加到代码中:
window = 3
offset = window - 1
y = [[''.join(map(str, ref[j:j+window])) for j in range(len(x[0])-offset)] \
for ref in x]
如果您想要几何或代数分析/解决方案,可以执行以下操作:
In [108]: x = np.array([[0,0,1,1],
...: [0,1,1,1],
...: [1,1,1,1]])
...:
In [109]:
In [109]: pairs = np.dstack((x[:, :-1], x[:, 1:]))
In [110]: x, y, z = pairs.shape
In [111]: uniques
Out[111]:
array([[0, 0],
[0, 1],
[1, 1]])
In [112]: uniques = np.unique(pairs.reshape(x*y, z), axis=0)
# None: 3d broadcasting is not recommended in any situation, please read doc for more details,
In [113]: R = (uniques[:,None][:,None,:] == pairs).all(3).sum(-1)
In [114]: R
Out[114]:
array([[1, 0, 0],
[1, 1, 0],
[1, 2, 3]])
In [116]: [{tuple(i): j for i,j in zip(uniques, i) if j} for i in R.T]
Out[116]: [{(0, 0): 1, (0, 1): 1, (1, 1): 1}, {(0, 1): 1, (1, 1): 2}, {(1, 1): 3}]
矩阵R
的列代表原始数组中每行uniques
对象中每个唯一对的计数
然后,您可以获得一个Python对象,如下所示:
In [108]: x = np.array([[0,0,1,1],
...: [0,1,1,1],
...: [1,1,1,1]])
...:
In [109]:
In [109]: pairs = np.dstack((x[:, :-1], x[:, 1:]))
In [110]: x, y, z = pairs.shape
In [111]: uniques
Out[111]:
array([[0, 0],
[0, 1],
[1, 1]])
In [112]: uniques = np.unique(pairs.reshape(x*y, z), axis=0)
# None: 3d broadcasting is not recommended in any situation, please read doc for more details,
In [113]: R = (uniques[:,None][:,None,:] == pairs).all(3).sum(-1)
In [114]: R
Out[114]:
array([[1, 0, 0],
[1, 1, 0],
[1, 2, 3]])
In [116]: [{tuple(i): j for i,j in zip(uniques, i) if j} for i in R.T]
Out[116]: [{(0, 0): 1, (0, 1): 1, (1, 1): 1}, {(0, 1): 1, (1, 1): 2}, {(1, 1): 3}]
这是一种使用卷积的方法。由于快速卷积依赖于FFT,因此需要使用浮点进行计算,我们有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))
在实际问题中,每个模式的最大位数是多少(对应于示例中的2)?@PaulPanzer每个消息的最大位数是64,我通常会看到每个模式8位,但最多可能是64位。我最多可以做53位。我会发布一个答案。@PaulPanzer你知道为什么在较小的数据集上FFT性能更差吗?显然,它在我实际使用的数据集上效果更好,但有趣的是,它在使用更多数据时效果更好。可能是开销。卷积需要一定的规模才能真正从fft中获利,低于这个规模,我想它无法抵消更复杂算法的成本。顺便说一句,我想我修正了行与列的错误,要不要把代码再转一圈?看起来太棒了!肯定比我想的更具可读性。你知道有多好吗。如果我想做3个长度的位,我会把
j:j+2
改成j:j+3
?看起来很棒!在您的实现中,从2增加位长度是否容易?例如,如果我想要8位长度的话?@JordanSosnowski当然。在这种情况下,您只是沿着第三个轴拉伸阵列。如果您的问题超过3D,则不!广播会有很大的开销。我刚刚意识到返回的数据是不正确的。因此,对于下面的示例,宽度为2的返回数据应该是a=np。数组([[0,0,1,1],[0,1,1,1],[1,1,1],[1,1,1,1],[0,0,0,0],[1,0,1,0]])输出=[{'00':