考虑以下列表:
l = [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0]
在1
小号细分列表分为5个部分:
l = [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0]
我希望每个部分n
在 a 之前不超过连续的零(如果可能)1
,但您不能擦除当前的1
s。也不应该有 1 互相跟随。
快速示例:假设 n = 3,l
应该是:
l = [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0]
对于 n = 2,它将是:
l = [0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1]
对于第一部分,我没有1
在两个零之后包含一个,因为那样你就会有两个1
s 互相跟随。
知道我该怎么做吗?
这是我尝试过的:
import numpy as np
max_number_of_cells_per_list = 3
l = [0, 0, 0, 1, 0, 0, 0,0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0]
print(l)
# Find position of 1
pos_1 =[i for i,x in enumerate(l) if x == 1]
# Get number of cells
pos_1.insert(0,0)
numb_cells = np.diff(pos_1)
n = np.round(np.divide(numb_cells,max_number_of_cells_per_list))
k = 0
j = 0
for i,li in enumerate(l):
if l[i] == 1:
if n[k] > 1:
add = int((i-j)/n[k])
for jj in range(int(n[k])):
if jj == n[k]-1:
jj = i
else:
jj += add
l[jj] = 1
k += 1
j = i
print(l)
如果您尝试运行代码,您会发现它对l
. 我不明白为什么......但如果你有更好/不同的想法,我不太有兴趣发现我的错误。:)
由于您使用的是 NumPy,这里有一个使用它的解决方案。请注意,它不是矢量化的,我不确定您是否可以对其进行矢量化,因为我们必须对数组执行分组操作,而 NumPy 没有太多功能(尽管我可能只是没有看到它)。
我将np.split
用于获取[0, ..., 1]
组,然后检查两种情况:首先,对于实际上不以1
(数组末尾的可能组)结尾的数组,以及具有多个n + 2
零的数组。然后我只是1
在每个n + 1
位置插入,确保不会有两个 1 在一起。
import numpy as np
a = np.array([0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0])
n = 3 # or n = 2, or any other n >= 0 value
result = []
for array in np.split(a.copy(), np.where(a == 1)[0] + 1):
last_index = -2 if array[-1] == 1 else None
array[n:last_index:n + 1] = 1
result.append(array)
np.concatenate(result)
# for n = 3: array([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0])
# for n = 2: array([0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1])
或者,我们可以只对 的索引进行操作,而不是将数组拆分为多个部分并对其进行操作1
。例如,在这里我得到 的初始索引1
,并使用以下方法添加更多的索引range
:
from itertools import tee
l = [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0]
n = 3
def pairwise(iterable):
"""s -> (s0, s1), (s1, s2), (s2, s3), ..."""
a, b = tee(iterable)
next(b, None)
return zip(a, b)
def one_indices(seq, n):
"""Returns new indices where we will put 1s"""
indices = [index + 1 for index, value in enumerate(seq) if value == 1]
complete_groups_count = len(indices) # those that end with 1
indices = [0, *indices, len(seq)]
for group_index, (start, end) in enumerate(pairwise(indices), start=1):
if group_index <= complete_groups_count:
yield from range(start + n, end - 2, n + 1)
yield end - 1
else: # last group that doesn't end with 1
yield from range(start + n, end, n + 1)
result = [0] * len(l)
for index in one_indices(l, 3):
result[index] = 1
result
# for n = 3: [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0]
# for n = 2: [0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1]
这可能比第一个示例中的拆分和连接数组更有效,但也更难以阅读。
最后,作为奖励,这是一个使用熊猫的解决方案。我在您之前的相关问题中看到您正在使用它,因此您可能会发现它很有用:
from functools import partial
import pandas as pd
def fill_ones(series, n):
last_index = -2 if series.iloc[-1] == 1 else None
series.iloc[n:last_index:n + 1] = 1
return series
l = [0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0]
s = pd.Series(l)
groups = s.shift().eq(1).cumsum()
fill_w_distance_3 = partial(fill_ones, n=3)
s.groupby(groups).transform(fill_w_distance_3).tolist()
# [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0]
fill_w_distance_2 = partial(fill_ones, n=2)
s.groupby(groups).transform(fill_w_distance_2).tolist()
# [0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1]
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句