Python 在列表中查找数量不断增加的组(具有不同的增量)
我有一个列表,其中包含具有不同增量的递增数字的“组”。下面是一个例子:Python 在列表中查找数量不断增加的组(具有不同的增量),python,pandas,numpy,Python,Pandas,Numpy,我有一个列表,其中包含具有不同增量的递增数字的“组”。下面是一个例子: l = [0, 1, 5, 8, 10, 20, 30, 40, 45, 48, 77, 100, 200, 300, 400] 我想回去: [[0], [1], [5], [8], [10, 20, 30, 40], [45], [48], [77], [100, 200, 300, 400]] 说明:0、1、5、8不遵循固定的增量(+1、+4、+3),而[10、20、30、40]都具有固定的+10增量 我知道如何使
l = [0, 1, 5, 8, 10, 20, 30, 40, 45, 48, 77, 100, 200, 300, 400]
我想回去:
[[0], [1], [5], [8], [10, 20, 30, 40], [45], [48], [77], [100, 200, 300, 400]]
说明:0、1、5、8不遵循固定的增量(+1、+4、+3),而[10、20、30、40]都具有固定的+10增量
我知道如何使用for循环和
curr_group
,curr_delta
等变量来实现这一点,但我希望避免这种情况
使用熊猫,我可以得到:
import pandas as pd
df = pd.DataFrame({'col': [0, 1, 5, 8, 10, 20, 30, 40, 45, 48, 77, 100, 200, 300, 400]})
df['shift_diff'] = (df.diff() != df.diff().shift(-1)).astype('int')
df['group'] = df.shift_diff.cumsum()
print list(df.groupby('group').col.apply(list))
哪个输出
[[0], [1], [5], [8], [10, 20, 30], [40], [45], [48], [77], [100, 200, 300], [400]]
非常接近,但是所有长度大于1的组([10,20,30]
和[100200300]
)都缺少最后一个元素
一个简短而优雅的解决方案将不胜感激!谢谢你这是你想要的吗
df['group'] = (~((df-df.shift()).diff().eq(0)|(df-df.shift(-1)).diff().eq(0))).cumsum()
print(list(df.groupby('group').col.apply(list)))
[[0], [1], [5], [8], [10, 20, 30, 40], [45], [48], [77], [100, 200, 300, 400]]
你不一定需要熊猫,尽管它可能更快。我不知道 我将解释作为注释放在代码中:
array = [1, 4, 5, 10, 20, 30, 40, 15, 17, 19, 2, 5, 3, 100, 200, 300, 400]
def f(array):
if len(array) == 1: return [array] # Special case for singleton array
if len(array) == 2: return [[array[0]], [array[1]]] # Special case for pair
results = []
index = 2
while index < len(array): # This will look back by 2, so if the array is too small, apply special cases
delta = array[index] - array[index - 1] # Difference between current and last element
if delta == array[index - 1] - array[index - 2]: # If the three elements are all equal
results.append(array[index - 2:index + 1]) # Append the group of the current three elements
index += 1 # Go forward one
while index < len(array) and delta == array[index] - array[index - 1]: # Keep adding until the list is exhausted or the next element is no longer part of this group
results[-1].append(array[index]) # Add the current element
index += 1
else: # If the three elements don't have the same deltas
results.append([array[index - 2]]) # Append the element and keep going
index += 1
return results
print(f(array))
array=[1,4,5,10,20,30,40,15,17,19,2,5,31000,200,300,400]
def f(阵列):
如果len(array)==1:返回[array]#单例数组的特例
如果len(array)==2:返回[[array[0]],[array[1]]]#pair的特殊情况
结果=[]
指数=2
而index
您可以在线试用,这也使阅读注释变得更容易,因为它足够宽,可以容纳注释。这里是一个python版本,它使用惰性函数查找列表中类似差异的长度。输入列表返回一个生成器,该生成器将返回共享差异的元素数,除非该差异是单数,在这种情况下,它将返回1 您可以使用它将列表切成块来创建新列表
from itertools import groupby
def diff_group_len(x):
dx = (x2-x1 for x1,x2 in zip(x,x[1:]))
dg = (len(tuple(g)) for _,g in groupby(dx))
SKIP = False
for group_size in dg:
if SKIP:
SKIP = False
continue
if group_size>1:
SKIP = True
yield group_size+1
else:
yield group_size
定义后,我们可以使用它在列表中查找束的长度。长度用于对列表进行切片
out = []
start = 0
for s in diff_group_len(l):
out.append(l[start:start+s])
start += s
out
# returns:
[[0],
[1],
[5],
[8],
[10, 20, 30, 40],
[45, 48, 51],
[77],
[100, 200, 300, 400]]
那是。。。美丽的。非常感谢!我有一种感觉,在那里的某个地方有一个布尔逻辑的把戏。荣誉请问你是怎么想出这个解决办法的?这是一种常见的差异/移位技巧吗?谢谢@GregSadetsky它是diff of diff,所以我们失去了每组两个单元格的信息,
shift
我们失去了底部的两个,shift
向上我们失去了顶部的两个,然后我们使用逻辑或
我们得到了所有:-)我想我得到了-(df df.shift()).diff()
计算增量增量的增量,而第二个(df.shift(-1)).diff()。只要增量的增量为0,数字就会有规律地增加(这.eq(0)
检查)。逻辑not和cumsum()完成了这幅图。太棒了!:-)再次感谢谢谢你,这太完美了!干杯