【问题标题】:Modified cumulative sum of numbers in a list修改后的列表中数字的累积总和
【发布时间】:2015-08-10 09:02:11
【问题描述】:

我想根据列表中数字的累积总和创建新列表。输入是理想的 - 可以拆分为子集,每个子​​集的总和相等。子集的长度不相等。输入子集的数量。

输出的每个子集代表增量整数[0,1,2,3,...],它替换原始输入。整数的个数就是子集的个数。

示例:

number of subsets = 2   

input = [1, 4, 5]
#cumsum = [1, 5, 10]
subsets = [1,5], [10]
output-subsets = [0,0], [1]
output = [0, 0, 1]

示例 1:

number of subsets = 4

input = [1, 2, 3, 4, 2, 5, 1, 6]
#cumsum = [1, 3, 6, 10, 12, 17, 18, 24]
subsets = [1,3,6], [10, 12],[17, 18], [24]
output-subsets = [0, 0, 0], [1, 1], [2, 2], [3]
output = [0, 0, 0, 1, 1, 2, 2, 3]

number of subsets = 2

input = [1, 2, 3, 4, 2, 5, 1, 6]
#cumsum = [1, 3, 6, 10, 12, 17, 18, 24]
subsets = [1, 3, 6, 10, 12],[17, 18, 24]
output-subsets = [0, 0, 0, 0, 0], [1, 1, 1]
output = [0, 0, 0, 0, 0, 1, 1, 1]

我尝试修改SO question:

def changelist(lis, t):
    total = 0

    s = sum(lis)
    subset = s/t

    for x in lis:
        total += x
        i= 1
        if(total <= subset):
            i = 0
        yield i


#changelist([input array], number of subset)    
print list(changelist([1, 2, 3, 4, 2, 5, 1, 6], 4))     

但只有第一个子集是正确的:

output = [0, 0, 0, 1, 1, 1, 1, 1]

我认为numpy.array_split 有问题strange behaviour of numpy array_split

我真的很想得到任何解释或帮助。

【问题讨论】:

  • 我不确定您要做什么。你能详细说明一下吗?
  • 您的第一个带有总和的块不清楚。我不知道为什么每行右侧显示的列表与总和相关联。该语句还需要详细说明:“输出的每个子集都表示增量整数,它替换原始输入:。”特别是,什么是“增量整数”?
  • 递增整数 - 我认为可以递增,例如 [0, 0, 0, 1, 1, 2, 2, 3, 4, 4, 4, 5, 5...] = 6如果子集的数量更高,则为子集
  • 你的问题很不清楚,numpy.array_split在哪里适合iit?
  • NumPy 的 array_split 分割成等长的子集。

标签: python list numpy numbers cumulative-sum


【解决方案1】:

这应该可以解决您的问题:

def changelist (l, t):
  subset = sum(l) / t
  current, total = 0, 0
  for x in l:
    total += x
    if total > subset:
      current, total = current + 1, x
    yield current

例子:

>>> list(changelist([1, 4, 5], 2))
[0, 0, 1]
>>> list(changelist([1, 2, 3, 4, 2, 5, 1, 6], 4))
[0, 0, 0, 1, 1, 2, 2, 3]
>>> list(changelist([1, 2, 3, 4, 2, 5, 1, 6], 2))
[0, 0, 0, 0, 0, 1, 1, 1]

它是如何工作的?

  • current 存储当前子集的“id”,total 存储当前子集的总和。
  • 对于初始列表l 中的每个元素x,如果此total 大于每个子集的预期总和(我的代码中的subset),则将其值添加到当前total ,那么您知道您在下一个子集 (current = current + 1) 中,并且您将当前子集的总数“重置”为实际元素 (total = x)。

【讨论】:

    【解决方案2】:

    您可以在将input 转换为向量化解决方案的数组后在此处使用NumPy,假设N 为子集的数量,如此处所列 -

    def modified_cumsum(input,N):
        A = np.asarray(input).cumsum()
        return np.append(False,np.in1d(A,(1+np.arange(N))*A[-1]/N))[:-1].cumsum()
    

    示例运行 -

    In [31]: N = 2  #number of subsets
        ...: input = [1, 4, 5]
        ...: 
    
    In [32]: modified_cumsum(input,N)
    Out[32]: array([0, 0, 1])
    
    In [33]: N = 4  #number of subsets
        ...: input = [1, 2, 3, 4, 2, 5, 1, 6]
        ...: 
    
    In [34]: modified_cumsum(input,N)
    Out[34]: array([0, 0, 0, 1, 1, 2, 2, 3])
    
    In [35]: N = 2  #number of subsets
        ...: input = [1, 2, 3, 4, 2, 5, 1, 6]
        ...: 
    
    In [36]: modified_cumsum(input,N)
    Out[36]: array([0, 0, 0, 0, 0, 1, 1, 1])
    

    【讨论】:

    • 对于这种事情,Numpy 比纯 python(Holt 解决方案)快吗?,+1
    • @jezrael 转换为 numpy 数组似乎是这里的瓶颈。除此之外,它应该是相当有效的。
    猜你喜欢
    • 2018-07-02
    • 2013-03-31
    • 1970-01-01
    • 1970-01-01
    • 2016-10-18
    • 1970-01-01
    • 2017-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多