一维阵列转换:在一定条件下将不同大小的组分配为唯一的批次

时间:2018-10-02 22:25:25

标签: python pandas numpy

问题: 创建最有效的函数,将1d数组(group_id列)转换为另一个1d数组(输出列)。

条件是:

  1. 最多n个组可以处于任何批次,在此示例中为n=2

  2. 每个批次必须包含相同大小的组。

  3. 测试条件:尽量减少批数。

该功能会将这些大小不同的组分配给具有唯一标识符的批次,条件是每个批次的大小都是固定的,并且每个批次仅包含相同大小的组。

data = {'group_size': [1,2,3,1,2,3,4,5,1,2,1,1,1],
        'batch_id':   [1,4,6,1,4,6,7,8,2,5,2,3,3]}
df = pd.DataFrame(data=data)
print(df)

    group_size  batch_id
0          1       1
1          2       4
2          3       6
3          1       1
4          2       4
5          3       6
6          4       7
7          5       8
8          1       2
9          2       5
10         1       2
11         1       3
12         1       3

我需要什么

some_function( data['group_size'] )给我data['batch_id']

编辑:

我的笨拙功能

def generate_array():

    out = 1
    batch_size = 2
    dictionary = {}

    for i in range(df['group_size'].max()):
        # get the mini df corresponding to the group size
        sub_df = df[df['group_size'] == i+1 ]
        # how many batches will we create?
        no_of_new_batches = np.ceil ( sub_df.shape[0] / batch_size )
        # create new array
        a = np.repeat(np.arange(out, out+no_of_new_batches ), batch_size)
        shift = len(a) - sub_df.shape[0]

        # remove last elements from array to match the size
        if len(a) != sub_df.shape[0]:
            a = a[0:-shift]

        # update batch id
        out = out + no_of_new_batches

        # create dictionary to store idx
        indexes = sub_df.index.values

        d = dict(zip(indexes, a))

        dictionary.update(d)

    array = [dictionary[i] for i in range(len(dictionary))]

    return array

generate_array()
Out[78]:
[1.0, 4.0, 6.0, 1.0, 4.0, 6.0, 7.0, 8.0, 2.0, 5.0, 2.0, 3.0, 3.0]

1 个答案:

答案 0 :(得分:2)

这是我的解决方案。我认为它提供的功能与您的功能不完全相同,但是它满足您的三个规则:

import numpy as np

def package(data, mxsz):
    idx = data.argsort()
    ds = data[idx]
    chng = np.empty((ds.size + 1,), bool)
    chng[0] = True
    chng[-1] = True
    chng[1:-1] = ds[1:] != ds[:-1]
    szs = np.diff(*np.where(chng))
    corr = (-szs) % mxsz
    result = np.empty_like(idx)
    result[idx] = (np.arange(idx.size) + corr.cumsum().repeat(szs)) // mxsz
    return result

data = np.random.randint(0, 4, (20,))
result = package(data, 3)
print(f'group_size {data}')
print(f'batch_id   {result}')
check = np.lexsort((data, result))
print('sorted:')
print(f'group_size {data[check]}')
print(f'batch_id   {result[check]}')

以n = 3运行的样本,输出的后两行与前两行相同,仅进行排序以便于检查:

group_size [1 1 0 1 2 0 2 2 2 3 1 2 3 2 1 0 1 0 2 0]
batch_id   [3 3 1 3 6 1 6 5 6 7 2 5 7 5 2 1 2 0 4 0]
sorted:
group_size [0 0 0 0 0 1 1 1 1 1 1 2 2 2 2 2 2 2 3 3]
batch_id   [0 0 1 1 1 2 2 2 3 3 3 4 5 5 5 6 6 6 7 7]

工作原理:

1)排序数据

2)检测排序后的数据在何处更改,以标识相等值的组(“组大小的组”)

3)确定各组大小的大小,并为每个大小计算n的整数倍的缺失

4)枚举排序的数据,同时每次切换到新的组大小组时,跳转到n的下一个整数倍;我们使用(3)以矢量化的方式完成

5)地板除以n以获取批次ID

6)改回原始顺序