将数字列表分组到给定窗口

时间:2018-02-14 10:31:20

标签: python pandas numpy

我有以下列表示例:

[-8,-7,-6,-5,-3,-2,-1,0,0,1,2,3,4,5,6,7]

我需要以下列方式对其进行分区: 例如给定window=2,我们总是从0开始为负数进行分组,从0开始为正数进行分组:

[-4,-3,-3,-2,-2,-1,-1,0,0,1,1,2,2,3,3,4]

e.g。给定window=3

[-3,-2,-2,-2,-1,-1,-1,0,0,1,1,1,2,2,2,3]

从0开始计算容器。所以我需要把左右两边的东西都归零。比如,[-5,-4,-3,-2,-1,0]window=2,我会将负数加在2的步骤中。让我们将列表反转为0以帮助更好地理解[0, -1, -2, -3, -4, -5],结果将是:

[-1, -2] turns into a bin -> [-1,-1]

[-3, -4] -> [-2, -2]

[-5, ] -> [-5, ]]

如果我同时有正数和负数,我会首先将左边的数字或最右边的数字中的0分开。另一个例子:

list = [-2,-1,0,0,0,1,2,3,4] window=2

所以我需要关注[-2,-1][1,2,3,4]。他们会变成:[-1,-1][1,1,2,2]。最终列表将是:[-1,-1,0,0,0,1,1,2,2]

我在使用Python 3.我尝试使用它,主要是伪代码:

def bin_positions(self, positions_list, bin_window):
    """ put relative positions into bins """

    binned_list = list()
    for index, element in enumerate(positions_list):
        if element == 0:
            # leave 0s untouched
            binned_list.append(element)
        elif element < 0:
            if index % bin_window == 0:
                # bin negative numbers
                pass
        elif element > 0:
            if index % bin_window == 0:
                # bin positive numbers
                pass
        # print(element, index)
    return binned_list

根据要求解释为什么我需要这个: 我正在进行NLP任务,我需要编码相对于句子中主要单词或短语的给定单词范围的位置嵌入。在我的例子中,主要短语的单词span用0表示。它左边的一个词,在右边索引为-1,索引为1,依此类推。我需要把这些位置分开,因为我不在乎这些词与主词有多远,而只是相对而言。因此,如果window=3,主要单词左侧的所有3个单词都可以索引为-1,-1,-1。

3 个答案:

答案 0 :(得分:2)

假设我正确理解了您的问题,并且所有索引都是有序的,我会使用numpy

import numpy as np

def bin_list(l, width):
    a = np.array(l)
    a[a>0] = (a[a>0]+(width-1))//width
    a[a<0] = (a[a<0])//width
    return list(a)

l = [i for i in range(-9,0)] + [0,0] + [i for i in range(1,10)]

print(l)
print(bin_list(l,2))
print(bin_list(l,3))
print(bin_list(l,4))

这给出了:

[-9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[-5, -4, -4, -3, -3, -2, -2, -1, -1, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5]
[-3, -3, -3, -2, -2, -2, -1, -1, -1, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3]
[-3, -2, -2, -2, -2, -1, -1, -1, -1, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3]

如果获得list作为不必要的约束,您可以将return list(a)更改为return a

答案 1 :(得分:1)

您可以将列表拆分为左右两个部分。然后分别处理它们并在最后连接它们。

def binlist(startlist, window):

    idx = [i for i,j in enumerate(startlist) if j == 0]

    left  = startlist[:idx[0]]
    right = startlist[idx[-1] + 1:]

    newleft  = []
    newright = []

    counter = -1
    for i, _ in enumerate(left[::-1], 1):
        newleft.append(counter)
        if i % window == 0:
            counter -= 1

    newleft = newleft[::-1]

    counter  = 1
    for i, _ in enumerate(right, 1):
        newright.append(counter)
        if i % window == 0:
            counter += 1

    final = newleft + [0 for i in idx] + newright

    return final

# your test lists:
print(binlist([-8,-7,-6,-5,-3,-2,-1,0,0,1,2,3,4,5,6,7], 2))
print(binlist([-8,-7,-6,-5,-3,-2,-1,0,0,1,2,3,4,5,6,7], 3))

输出:

[-4, -3, -3, -2, -2, -1, -1, 0, 0, 1, 1, 2, 2, 3, 3, 4]
[-3, -2, -2, -2, -1, -1, -1, 0, 0, 1, 1, 1, 2, 2, 2, 3]

答案 2 :(得分:1)

这适用于您的示例,但您需要对其进行测试以确保其具体化。

import numpy as np

window=3
array = np.array([-8,-7,-6,-5,-3,-2,-1,0,0,1,2,3,4,5,6,7])
RH = np.ceil(array[np.where( array > 0 )]/window)
result = np.hstack([-1*RH[::-1],0,0,RH])