numpy.array_split() odd behavior

Refresh

December 2018

Views

1.3k time

3

I'm trying to split a large data frame with cycle data into smaller data frames of equal , or near equal, cycle length. Array_split was working great until my data would not allow equal split (worked fine with 500,000 cycles,but not with 1,190,508). I'm wanting the sections to be in 1000 cycle increments (except the last frame would be less).

Here's the scenario:

d = {
'a': pd.Series(random(1190508)),
'b': pd.Series(random(1190508)),
'c': pd.Series(random(1190508)),
}

frame = pd.DataFrame(d)

cycles = 1000  
sections = math.ceil(len(frame)/cycles)

split_frames = np.array_split(frame, sections)

The docs show array_split basically splitting even groups while it can, then making smaller group at the end because the data can't be divided evenly. This is what I want, but currently, if I look at the lengths of each frame in this new split_frames list:

split_len = pd.DataFrame([len(a) for a in split_frame])

split_len.to_csv('lengths.csv')

the lengths of the first 698 frames are 1000 elements, but then the rest (frame 699 to 1190) are 999 elements in length.

It seems to make this randomly occurring break in length no matter what number I pass for sections (rounding, even number, or whatever else).

I'm struggling to understand why it's not creating equal frame lengths except the last one like in the docs:

>>> x = np.arange(8.0)
>>> np.array_split(x, 3)
    [array([ 0.,  1.,  2.]), array([ 3.,  4.,  5.]), array([ 6.,  7.])] 

Any help is appreciated, thanks!

khu

4 answers

4

array_splitне делает число равных частей и одна с остатками. Если разделить массив длины lв nсекцию, это l % nучастки размера l//n + 1и остальные размеров l//n. Смотрите источник для получения более подробной информации. (Это действительно должно быть объяснено в документации.)

-1

как получить доступ к результату каждого раскола

x = np.arange(8.0)

у = np.array_split (х, 3) [массив ([0, 1, 2.]), массив ([3, 4, 5]), массив ([6, 7])]

как получить у (1), у (2), у (3)

0

Простой пример того, что другие объяснения:

In [21]: [len(x)for x in np.array_split(np.arange(1000),12)]
Out[21]: [84, 84, 84, 84, 83, 83, 83, 83, 83, 83, 83, 83]
3

Как пишет @ user2357112, array_splitне делать то , что вы думаете , что делает ... но глядя на документы, это трудно понять , что он делает, в любом случае. На самом деле, я бы сказал , что его поведение не определено . Мы ожидаем , что он вернется что - то , но мы не знаем , какие свойства , что - то будет.

Для того, чтобы получить то , что вы хотите, я хотел бы использовать numpy.split«ы способность предоставлять пользовательские индексы. Так, например:

def greedy_split(arr, n, axis=0):
    """Greedily splits an array into n blocks.

    Splits array arr along axis into n blocks such that:
        - blocks 1 through n-1 are all the same size
        - the sum of all block sizes is equal to arr.shape[axis]
        - the last block is nonempty, and not bigger than the other blocks

    Intuitively, this "greedily" splits the array along the axis by making
    the first blocks as big as possible, then putting the leftovers in the
    last block.
    """
    length = arr.shape[axis]

    # compute the size of each of the first n-1 blocks
    block_size = np.ceil(length / float(n))

    # the indices at which the splits will occur
    ix = np.arange(block_size, length, block_size)

    return np.split(arr, ix, axis)

Некоторые примеры:

>>> x = np.arange(10)
>>> greedy_split(x, 2)
[array([0, 1, 2, 3, 4]), array([5, 6, 7, 8, 9])]
>>> greedy_split(x, 3)
[array([0, 1, 2, 3]), array([4, 5, 6, 7]), array([8, 9])]
>>> greedy_split(x, 4)
[array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8]), array([9])]
jme